<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Spryker Documentation</title>
        <description>Spryker documentation center.</description>
        <link>https://docs.spryker.com/</link>
        <atom:link href="https://docs.spryker.com/feed.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Wed, 06 May 2026 15:28:30 +0000</lastBuildDate>
        <generator>Jekyll v4.2.2</generator>
        
        
        <item>
            <title>Enable Dynamic Multistore</title>
            <description>&lt;p&gt;This document describes how to enable &lt;a href=&quot;/docs/pbc/all/dynamic-multistore/latest/base-shop/dynamic-multistore-feature-overview.html&quot;&gt;Dynamic Multistore&lt;/a&gt; (DMS).&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;If your project version is below 202307.0, &lt;a href=&quot;/docs/pbc/all/dynamic-multistore/latest/base-shop/install-and-upgrade/install-features/install-dynamic-multistore.html&quot;&gt;Install Dynamic Multistore&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;enable-dynamic-multistore&quot;&gt;Enable Dynamic Multistore&lt;/h3&gt;
&lt;section class=&apos;info-block info-block--warning&apos;&gt;&lt;i class=&apos;info-block__icon icon-warning&apos;&gt;&lt;/i&gt;&lt;div class=&apos;info-block__content&apos;&gt;&lt;div class=&quot;info-block__title&quot;&gt;Staging environment&lt;/div&gt;
To avoid unexpected downtime and data loss, perform and test *all* of the following steps in a staging environment first.
&lt;/div&gt;&lt;/section&gt;
&lt;ol&gt;
&lt;li&gt;Replace &lt;code&gt;StoreClient::getCurrentStore()&lt;/code&gt; and &lt;code&gt;StoreFacade::getCurrentStore()&lt;/code&gt; methods with &lt;code&gt;StoreStorageClient:getStoreNames()&lt;/code&gt;, &lt;code&gt;StoreStorageClient::findStoreByName()&lt;/code&gt;, or &lt;code&gt;StoreFacade::getStoreCollection()&lt;/code&gt; in the following:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Back Office&lt;/li&gt;
&lt;li&gt;Merchant Portal&lt;/li&gt;
&lt;li&gt;Console Commands&lt;/li&gt;
&lt;li&gt;Gateway&lt;/li&gt;
&lt;li&gt;BackendAPI&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Update custom console commands to meet the following rules:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Store(Facade|Client)::getCurrentStore()&lt;/code&gt; isn’t used in the code a console command executes.&lt;/li&gt;
&lt;li&gt;All store-aware commands implement &lt;code&gt;Spryker\Zed\Kernel\Communication\Console\StoreAwareConsole&lt;/code&gt; and execute actions for a specific store if a store parameter is provided; if not provided, actions are executed for all the stores in the region.&lt;/li&gt;
&lt;li&gt;Optional: We recommend using the &lt;code&gt;--store&lt;/code&gt; parameter instead of &lt;code&gt;APPLICATION_STORE&lt;/code&gt; env variable; both methods are supported.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;
&lt;p&gt;After enabling DMS, the basic domain structure must change from store to region for all the applications. For example, &lt;code&gt;https://yves.de.mysprykershop.com&lt;/code&gt; will change to &lt;code&gt;https://yves.eu.mysprykershop.com&lt;/code&gt;. To prevent negative SEO effects, set up the needed redirects. If your target domain doesn’t change, for example it doesn’t contain a region name - yves.mysprykershop.com - you may skip this step.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update AWS deployment files to DMS mode using the example:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Original environment variables section:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_BEFORE_DEPLOY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;pre-deploy.dynamic-store-off&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_AFTER_DEPLOY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_INSTALL&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;production.dynamic-store-off&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--no-ansi&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_DESTRUCTIVE_INSTALL&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;destructive.dynamic-store-off&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--no-ansi&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_YVES_HOST_DE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;de.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_YVES_HOST_AT&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;at.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Updated environment variables section:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_BEFORE_DEPLOY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;pre-deploy&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_AFTER_DEPLOY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_INSTALL&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;dynamic-store&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--no-ansi&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_DESTRUCTIVE_INSTALL&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;destructive&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--no-ansi&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_DYNAMIC_STORE_MODE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_YVES_HOST_EU&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yves.eu.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Original regions section:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;regions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;stores&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;DE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;broker&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;de_queue&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;key_value_store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;de_search&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;AT&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;broker&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;at_queue&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;key_value_store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;at_search&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Updated regions section:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;regions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;broker&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;eu-docker&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;key_value_store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;eu_search&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Before first deployment&lt;/strong&gt;, create a support case and provide the deploy.ABC.yml file that contains the dynamic multistore setup. For example: “We have added the dynamic multistore setup to our deploy.ABC.yml and would like it to be activated.”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DMS changes the structure of RabbitMQ messages. When you’re ready for the migration, wait for all the remaining messages in the queue to be processed. When the queue is empty, enable the maintenance mode.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The downtime associated with the maintenance mode is limited to the deployment time, which usually takes up to an hour.&lt;/p&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;Run a normal deploy for your server pipeline.&lt;/li&gt;
&lt;/ol&gt;
&lt;section class=&apos;info-block info-block--warning&apos;&gt;&lt;i class=&apos;info-block__icon icon-warning&apos;&gt;&lt;/i&gt;&lt;div class=&apos;info-block__content&apos;&gt;&lt;div class=&quot;info-block__title&quot;&gt;Verification&lt;/div&gt;
- Make sure your store is available at `https://yves.eu.mysprykershop.com` or `https://backoffice.eu.mysprykershop.com`.
- Make sure the store switcher is displayed on the Storefront.
&lt;/div&gt;&lt;/section&gt;
&lt;p&gt;Your shop is now running in DMS mode.&lt;/p&gt;
&lt;h3 id=&quot;check-if-dynamic-multistore-is-enabled&quot;&gt;Check if Dynamic Multistore is enabled&lt;/h3&gt;
&lt;p&gt;DMS is enabled if at least one of the following applies:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using environment: If the value of &lt;code&gt;SPRYKER_DYNAMIC_STORE_MODE&lt;/code&gt; environment variable is &lt;code&gt;true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Using interface: In the Back Office &amp;gt; &lt;strong&gt;Administration&lt;/strong&gt; &amp;gt; &lt;strong&gt;Stores&lt;/strong&gt;, an &lt;strong&gt;Edit&lt;/strong&gt; button is displayed next to each store.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;disable-dynamic-multistore&quot;&gt;Disable Dynamic Multistore&lt;/h2&gt;
&lt;section class=&apos;info-block info-block--warning&apos;&gt;&lt;i class=&apos;info-block__icon icon-warning&apos;&gt;&lt;/i&gt;&lt;div class=&apos;info-block__content&apos;&gt;&lt;div class=&quot;info-block__title&quot;&gt;Staging environment&lt;/div&gt;
To avoid unexpected downtime and data loss, perform and test *all* of the following steps in a staging environment first.
&lt;/div&gt;&lt;/section&gt;
&lt;ol&gt;
&lt;li&gt;After disabling DMS, the basic domain structure will change from region to store for all the applications. To prevent negative SEO effects, set up the needed redirects.&lt;/li&gt;
&lt;li&gt;DMS changes the structure of RabbitMQ messages. When you’re ready for the migration, wait for all the remaining messages in the queue to be processed. When the queue is empty, enable the maintenance mode.
(Expected downtime is limited to the deployment time, normally it takes less than 1hr)&lt;/li&gt;
&lt;li&gt;Revert changes in deploy files to disable DMS:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Original environment variables section:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_BEFORE_DEPLOY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;pre-deploy&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_AFTER_DEPLOY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_INSTALL&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;dynamic-store&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--no-ansi&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_DESTRUCTIVE_INSTALL&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;destructive&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--no-ansi&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_DYNAMIC_STORE_MODE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_YVES_HOST_EU&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yves.eu.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Updated environment variables section:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_BEFORE_DEPLOY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;pre-deploy.dynamic-store-off&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_AFTER_DEPLOY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_INSTALL&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;production.dynamic-store-off&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--no-ansi&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_HOOK_DESTRUCTIVE_INSTALL&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;vendor/bin/install&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;destructive.dynamic-store-off&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--no-ansi&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-vvv&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_YVES_HOST_DE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;de.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SPRYKER_YVES_HOST_AT&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;at.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Original regions section:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;regions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;broker&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;eu-docker&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;key_value_store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;eu_search&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Updated regions section:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;regions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;stores&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;DE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;broker&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;de_queue&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;key_value_store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;de_search&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;AT&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;broker&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;at_queue&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;key_value_store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;at_search&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;Run a normal deploy for your server pipeline.&lt;/li&gt;
&lt;/ol&gt;
&lt;section class=&apos;info-block info-block--warning&apos;&gt;&lt;i class=&apos;info-block__icon icon-warning&apos;&gt;&lt;/i&gt;&lt;div class=&apos;info-block__content&apos;&gt;&lt;div class=&quot;info-block__title&quot;&gt;Verification&lt;/div&gt;
- Make sure your store is available at `https://yves.de.mysprykershop.com` or `https://backoffice.de.mysprykershop.com`.
- Make sure the store switcher is *not* displayed on the Storefront.
&lt;/div&gt;&lt;/section&gt;
</description>
            <pubDate>Wed, 06 May 2026 15:23:25 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/dynamic-multistore/latest/base-shop/enable-dynamic-multistore.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/dynamic-multistore/latest/base-shop/enable-dynamic-multistore.html</guid>
            
            
        </item>
        
        <item>
            <title>Migration status - Glue API to API Platform</title>
            <description>This document tracks Spryker&apos;s migration of API-providing modules to the **API Platform** (built on Symfony and the API Platform library). Use it to plan upgrades and check the current status of every module.

{% info_block infoBox &quot;Looking for the integration guide?&quot; %}

This page does **not** describe how to integrate API Platform into your project. For step-by-step integration instructions, see:

- [Migrate to API Platform](/docs/dg/dev/upgrade-and-migrate/migrate-to-api-platform.html)
- [Integrate API Platform](/docs/dg/dev/upgrade-and-migrate/integrate-api-platform.html)
- [Integrate API Platform security](/docs/dg/dev/upgrade-and-migrate/integrate-api-platform-security.html)
- [API Platform architecture](/docs/dg/dev/architecture/api-platform.html)

{% endinfo_block %}

## Why Spryker is moving to API Platform

API Platform replaces Spryker-specific patterns for routing, authentication, and resource definition with industry-standard Symfony conventions, automatic OpenAPI schema generation, and a clean separation between resource schema, provider, and validation.

| Aspect | Previous infrastructure | API Platform |
|---|---|---|
| Bootstrap | Spryker-specific application bootstrap | Symfony Kernel-based routing |
| Resource registration | Manual plugin registration in `GlueApplicationDependencyProvider` | Declarative YAML resource definitions (`*.resource.yml`) |
| Authentication | Custom flows per module | Standard OAuth2 / Symfony Security |
| Coupling | Tight coupling between resource and routing logic | Clean separation: provider + resource schema + validation |
| Testability | Complex to test and extend | Symfony-native, testable with standard PHPUnit patterns |
| OpenAPI | Manual / partial | Automatic OpenAPI schema generation |

## General migration workflow

For any module marked **Migrated**, projects upgrade in three high-level steps. Detailed instructions are in the linked integration guides above.

1. **Update the module to the API Platform-enabled version**

   Pull the new module version that ships the `*.resource.yml` schema and Provider class:

    ```bash
    composer update spryker/&lt;module-name&gt;
    ```

2. **Remove the previous resource plugins**

   In your project&apos;s `GlueApplicationDependencyProvider`, remove the previous plugin registrations for the migrated module - typically a `ResourceRoutePlugin` (and any related `ResourceRelationshipPlugin` / expander plugins) registered in `getResourceRoutePlugins()`.

   For **extension-only** modules, remove or replace the corresponding plugin wiring in the parent module&apos;s dependency provider as indicated in the module&apos;s release notes.

3. **Clear caches and verify**

    ```bash
    vendor/bin/glue cache:clear
    vendor/bin/glue api:generate
    ```

   Confirm the endpoint is served by API Platform by hitting it against your local Glue host - the response is now produced by the new Symfony-based stack.

{% info_block infoBox &quot;Parallel operation&quot; %}

The previous API stack and API Platform run **side by side** during the transition. You can migrate modules incrementally; modules that have not been migrated continue to be served by the previous stack.

{% endinfo_block %}

### Status legend

| Status | Meaning |
|---|---|
| Migrated | Module is available on API Platform and production-ready. |
| Planned | Module is scheduled or queued for migration to API Platform. |

## Storefront API modules

All StorefrontAPI and Extension-only StorefrontAPI modules. Migrated modules are listed first.

| Module | Category | Status   | Key endpoints |
|---|---|----------|---|
| ContentProductAbstractListsRestApi | StorefrontAPI | Migrated | GET /content-product-abstract-lists/{id}&lt;br&gt;GET /content-product-abstract-lists/{id}/abstract-products |
| MerchantOpeningHoursRestApi | StorefrontAPI | Migrated | GET /merchants/{id}/merchant-opening-hours |
| MerchantProductOffersRestApi | StorefrontAPI | Migrated | GET /concrete-products/{id}/product-offers&lt;br&gt;GET /product-offers/{id} |
| OrderPaymentsRestApi | StorefrontAPI | Migrated | POST /order-payments |
| PaymentsRestApi | StorefrontAPI | Migrated | POST /payments&lt;br&gt;POST /payment-cancellations&lt;br&gt;POST /payment-customers |
| ProductAvailabilitiesRestApi | StorefrontAPI | Migrated | GET /abstract-products/{id}/abstract-product-availabilities&lt;br&gt;GET /concrete-products/{id}/concrete-product-availabilities |
| ProductOfferAvailabilitiesRestApi | StorefrontAPI | Migrated | GET /product-offers/{id}/product-offer-availabilities |
| ProductOfferPricesRestApi | StorefrontAPI | Migrated | GET /product-offers/{id}/product-offer-prices |
| ProductPricesRestApi | StorefrontAPI | Migrated | GET /abstract-products/{id}/abstract-product-prices&lt;br&gt;GET /concrete-products/{id}/concrete-product-prices |
| ProductTaxSetsRestApi | StorefrontAPI | Migrated | GET /abstract-products/{id}/product-tax-sets |
| ProductsRestApi | StorefrontAPI | Migrated | GET /abstract-products/{id}&lt;br&gt;GET /concrete-products/{id} |
| StoresApi | StorefrontAPI | Migrated | GET /stores |
| AgentAuthRestApi | StorefrontAPI | Migrated | POST /agent-access-tokens&lt;br&gt;POST /agent-customer-impersonation-access-tokens&lt;br&gt;GET /agent-customer-search |
| AlternativeProductsRestApi | StorefrontAPI | Planned  | GET /abstract-products/{id}/related-products&lt;br&gt;GET /concrete-products/{id}/abstract-alternative-products&lt;br&gt;GET /concrete-products/{id}/concrete-alternative-products |
| AuthRestApi | StorefrontAPI | Migrated | POST /token&lt;br&gt;POST /access-tokens&lt;br&gt;POST /refresh-tokens&lt;br&gt;DELETE /refresh-tokens/{id} |
| AvailabilityNotificationsRestApi | StorefrontAPI | Planned  | POST /availability-notifications&lt;br&gt;DELETE /availability-notifications/{id}&lt;br&gt;GET /my-availability-notifications&lt;br&gt;GET /customers/{id}/availability-notifications |
| CartCodesRestApi | StorefrontAPI | Planned  | POST /carts/{id}/cart-codes&lt;br&gt;DELETE /carts/{id}/cart-codes/{id}&lt;br&gt;POST /guest-carts/{id}/cart-codes&lt;br&gt;DELETE /guest-carts/{id}/cart-codes/{id} |
| CartPermissionGroupsRestApi | StorefrontAPI | Planned  | GET /cart-permission-groups&lt;br&gt;GET /cart-permission-groups/{id} |
| CartReorderRestApi | StorefrontAPI | Planned  | POST /cart-reorder |
| CartsRestApi | StorefrontAPI | Planned  | GET,POST /carts&lt;br&gt;GET,PATCH,DELETE /carts/{id}&lt;br&gt;POST /carts/{id}/items&lt;br&gt;PATCH,DELETE /carts/{id}/items/{id}&lt;br&gt;GET /guest-carts&lt;br&gt;GET,PATCH /guest-carts/{id}&lt;br&gt;POST /guest-carts/{id}/guest-cart-items&lt;br&gt;PATCH,DELETE /guest-carts/{id}/guest-cart-items/{id}&lt;br&gt;GET /customers/{id}/carts |
| CatalogSearchRestApi | StorefrontAPI | Migrated | GET /catalog-search&lt;br&gt;GET /catalog-search-suggestions |
| CategoriesRestApi | StorefrontAPI | Migrated | GET /category-trees&lt;br&gt;GET /category-nodes/{id} |
| CheckoutRestApi | StorefrontAPI | Planned  | POST /checkout-data&lt;br&gt;POST /checkout |
| CmsPagesRestApi | StorefrontAPI | Planned  | GET /cms-pages&lt;br&gt;GET /cms-pages/{id} |
| CompaniesRestApi | StorefrontAPI | Migrated | GET /companies&lt;br&gt;GET /companies/{id} |
| CompanyBusinessUnitAddressesRestApi | StorefrontAPI | Planned  | GET /company-business-unit-addresses&lt;br&gt;GET /company-business-unit-addresses/{id} |
| CompanyBusinessUnitsRestApi | StorefrontAPI | Planned  | GET /company-business-units&lt;br&gt;GET /company-business-units/{id} |
| CompanyRolesRestApi | StorefrontAPI | Planned  | GET /company-roles&lt;br&gt;GET /company-roles/{id} |
| CompanyUserAuthRestApi | StorefrontAPI | Planned  | POST /company-user-access-tokens |
| CompanyUsersRestApi | StorefrontAPI | Planned  | GET /company-users&lt;br&gt;GET /company-users/{id} |
| ConfigurableBundleCartsRestApi | StorefrontAPI | Planned  | POST /carts/{id}/configured-bundles&lt;br&gt;PATCH,DELETE /carts/{id}/configured-bundles/{id}&lt;br&gt;POST,PATCH,DELETE /guest-carts/{id}/guest-configured-bundles/{id} |
| ConfigurableBundlesRestApi | StorefrontAPI | Planned  | GET /configurable-bundle-templates&lt;br&gt;GET /configurable-bundle-templates/{id} |
| ContentBannersRestApi | StorefrontAPI | Planned  | GET /content-banners/{id} |
| CustomerAccessRestApi | StorefrontAPI | Migrated | GET /customer-access |
| CustomersRestApi | StorefrontAPI | Migrated | GET,POST /customers&lt;br&gt;GET,PATCH,DELETE /customers/{id}&lt;br&gt;GET,POST /customers/{id}/addresses&lt;br&gt;GET,PATCH,DELETE /customers/{id}/addresses/{id}&lt;br&gt;POST /customer-forgotten-password&lt;br&gt;PATCH /customer-restore-password/{id}&lt;br&gt;PATCH /customer-password/{id}&lt;br&gt;POST /customer-confirmation |
| DiscountPromotionsRestApi | Extension-Only-StorefrontAPI | Planned  | CartsRestApi, CartCodesRestApi |
| DiscountsRestApi | StorefrontAPI | Planned  | POST /carts/{id}/vouchers&lt;br&gt;DELETE /carts/{id}/vouchers/{id}&lt;br&gt;POST /guest-carts/{id}/vouchers&lt;br&gt;DELETE /guest-carts/{id}/vouchers/{id} |
| EntityTagsRestApi | Extension-only StorefrontAPI | Planned  | GlueApplication |
| GiftCardsRestApi | Extension-only StorefrontAPI | Planned  | GlueApplication |
| MerchantCategoriesRestApi | Extension-only StorefrontAPI | Planned  | MerchantsRestApi |
| MerchantProductOfferServicePointAvailabilitiesRestApi | Extension-only StorefrontAPI | Planned  | (transfer-only) |
| MerchantProductOfferShoppingListsRestApi | Extension-only StorefrontAPI | Planned  | (transfer-only) |
| MerchantProductOfferWishlistRestApi | Extension-only StorefrontAPI | Planned  | WishlistsRestApi |
| MerchantProductShoppingListsRestApi | Extension-only StorefrontAPI | Planned  | (transfer-only) |
| MerchantProductsRestApi | Extension-only StorefrontAPI | Planned  | CartsRestApi |
| MerchantRelationshipProductListsRestApi | Extension-only StorefrontAPI | Planned  | CustomersRestApi |
| MerchantSalesReturnsRestApi | Extension-only StorefrontAPI | Planned  | (transfer-only) |
| MerchantShipmentsRestApi | Extension-only StorefrontAPI | Planned  | ShipmentsRestApi |
| MerchantsRestApi | StorefrontAPI | Planned  | GET /merchants&lt;br&gt;GET /merchants/{id}&lt;br&gt;GET /merchants/{id}/merchant-addresses |
| MultiCartsRestApi | Extension-only StorefrontAPI | Planned  | CartsRestApi |
| NavigationsRestApi | StorefrontAPI | Migrated | GET /navigations/{id} |
| OauthApi | StorefrontAPI | Migrated | POST /token |
| OmsRestApi | Extension-only StorefrontAPI | Planned  | OrdersRestApi |
| OrderAmendmentsRestApi | Extension-only StorefrontAPI | Planned  | OrdersRestApi, CartsRestApi, CartReorderRestApi |
| OrdersRestApi | StorefrontAPI | Planned  | GET /orders&lt;br&gt;GET /orders/{id}&lt;br&gt;GET /customers/{id}/orders |
| PriceProductOfferVolumesRestApi | Extension-only StorefrontAPI | Planned  | ProductOfferPricesRestApi |
| PriceProductVolumesRestApi | Extension-only StorefrontAPI | Planned  | ProductPricesRestApi |
| ProductAttributesRestApi | StorefrontAPI | Migrated | GET /product-management-attributes&lt;br&gt;GET /product-management-attributes/{id} |
| ProductBundleCartsRestApi | Extension-only StorefrontAPI | Planned  | CartsRestApi, ShipmentsRestApi |
| ProductBundlesRestApi | StorefrontAPI | Planned  | GET /concrete-products/{id}/bundled-products |
| ProductConfigurationShoppingListsRestApi | Extension-only StorefrontAPI | Planned  | ShoppingListsRestApi |
| ProductConfigurationWishlistsRestApi | Extension-only StorefrontAPI | Planned  | WishlistsRestApi |
| ProductConfigurationsPriceProductVolumesRestApi | Extension-only StorefrontAPI | Planned  | ProductConfigurationsRestApi, ProductConfigurationShoppingListsRestApi, ProductConfigurationWishlistsRestApi |
| ProductConfigurationsRestApi | Extension-only StorefrontAPI | Planned  | ProductsRestApi, CartsRestApi, OrdersRestApi |
| ProductDiscontinuedRestApi | Extension-only StorefrontAPI | Planned  | ProductsRestApi |
| ProductImageSetsRestApi | StorefrontAPI | Migrated | GET /abstract-products/{id}/abstract-product-image-sets&lt;br&gt;GET /concrete-products/{id}/concrete-product-image-sets |
| ProductLabelsRestApi | StorefrontAPI | Planned  | GET /product-labels/{id} |
| ProductMeasurementUnitsRestApi | StorefrontAPI | Planned  | GET /product-measurement-units/{id}&lt;br&gt;GET /concrete-products/{id}/sales-units |
| ProductOfferSalesRestApi | Extension-only StorefrontAPI | Planned  | (transfer-only) |
| ProductOfferServicePointAvailabilitiesRestApi | StorefrontAPI | Planned  | POST /product-offer-service-point-availabilities |
| ProductOfferShoppingListsRestApi | Extension-only StorefrontAPI | Planned  | (transfer-only) |
| ProductOffersRestApi | Extension-only StorefrontAPI | Planned  | ProductsRestApi |
| ProductOptionsRestApi | Extension-only StorefrontAPI | Planned  | CartsRestApi, OrdersRestApi, ProductsRestApi, QuoteRequestsRestApi |
| ProductReviewsRestApi | StorefrontAPI | Planned  | GET,POST /abstract-products/{id}/product-reviews&lt;br&gt;GET /abstract-products/{id}/product-reviews/{id} |
| QuoteRequestAgentsRestApi | StorefrontAPI | Planned  | GET,POST /agent-quote-requests&lt;br&gt;GET,PATCH /agent-quote-requests/{id}&lt;br&gt;POST /agent-quote-requests/{id}/agent-quote-request-cancel&lt;br&gt;POST /agent-quote-requests/{id}/agent-quote-request-revise&lt;br&gt;POST /agent-quote-requests/{id}/agent-quote-request-send-to-customer |
| QuoteRequestsRestApi | StorefrontAPI | Planned  | GET,POST /quote-requests&lt;br&gt;GET,PATCH /quote-requests/{id}&lt;br&gt;POST /quote-requests/{id}/quote-request-cancel&lt;br&gt;POST /quote-requests/{id}/quote-request-revise&lt;br&gt;POST /quote-requests/{id}/quote-request-send-to-user&lt;br&gt;POST /quote-requests/{id}/quote-request-convert-to-quote |
| RelatedProductsRestApi | StorefrontAPI | Planned  | GET /abstract-products/{id}/related-products |
| SalesOrderThresholdsRestApi | Extension-only StorefrontAPI | Planned  | CartsRestApi, CheckoutRestApi |
| SalesReturnsRestApi | StorefrontAPI | Planned  | GET /return-reasons&lt;br&gt;GET,POST /returns&lt;br&gt;GET /returns/{id} |
| SecurityBlockerRestApi | Extension-only StorefrontAPI | Planned  | GlueApplication |
| ServicePointCartsRestApi | Extension-only StorefrontAPI | Planned  | CheckoutRestApi |
| ServicePointsRestApi | StorefrontAPI | Planned  | GET /service-points&lt;br&gt;GET /service-points/{id}&lt;br&gt;GET /service-points/{id}/service-point-addresses/{id} |
| SharedCartsRestApi | StorefrontAPI | Planned  | POST /carts/{id}/shared-carts&lt;br&gt;PATCH,DELETE /shared-carts/{id} |
| ShipmentTypeProductOfferServicePointAvailabilitiesRestApi | Extension-only StorefrontAPI | Planned  | ProductOfferServicePointAvailabilitiesRestApi |
| ShipmentTypeServicePointsRestApi | Extension-only StorefrontAPI | Planned  | CheckoutRestApi, ShipmentsRestApi, ShipmentTypesRestApi |
| ShipmentTypesRestApi | StorefrontAPI | Planned  | GET /shipment-types&lt;br&gt;GET /shipment-types/{id} |
| ShipmentsRestApi | Extension-only StorefrontAPI | Planned  | CheckoutRestApi, OrdersRestApi, QuoteRequestsRestApi |
| ShoppingListsRestApi | StorefrontAPI | Planned  | GET,POST /shopping-lists&lt;br&gt;GET,PATCH,DELETE /shopping-lists/{id}&lt;br&gt;POST /shopping-lists/{id}/shopping-list-items&lt;br&gt;PATCH,DELETE /shopping-lists/{id}/shopping-list-items/{id} |
| TaxAppRestApi | StorefrontAPI | Planned  | POST /tax-id-validate |
| UpSellingProductsRestApi | StorefrontAPI | Planned  | GET /carts/{id}/up-selling-products&lt;br&gt;GET /guest-carts/{id}/up-selling-products |
| UrlsRestApi | StorefrontAPI | Planned  | GET /url-resolver |
| WishlistsRestApi | StorefrontAPI | Planned  | GET,POST /wishlists&lt;br&gt;GET,PATCH,DELETE /wishlists/{id}&lt;br&gt;POST /wishlists/{id}/wishlist-items&lt;br&gt;PATCH,DELETE /wishlists/{id}/wishlist-items/{id} |

## Backend API modules

All BackendAPI modules tracked in the migration scope.

| Module | Category | Status | Key endpoints |
|---|---|---|---|
| CartNotesBackendApi | Extension-Only BackendAPI | Planned | SalesOrdersBackendApi |
| CategoriesBackendApi | BackendAPI | Planned | GET,POST /categories&lt;br&gt;GET,PATCH /categories/{id} |
| DynamicEntityBackendApi | BackendAPI | Planned | GET,POST,PATCH,PUT /dynamic-entity/{entity-name} (~62 auto-generated entity endpoints) |
| OauthBackendApi | BackendAPI | Planned | POST /token |
| PickingListsBackendApi | BackendAPI | Planned | GET /picking-lists&lt;br&gt;GET /picking-lists/{id}&lt;br&gt;PATCH /picking-lists/{id}/picking-list-items/{id}&lt;br&gt;POST /start-picking |
| PickingListsUsersBackendApi | Extension-Only BackendAPI | Planned | PickingListsBackendApi |
| PickingListsWarehousesBackendApi | Extension-Only BackendAPI | Planned | PickingListsBackendApi |
| ProductAttributesBackendApi | BackendAPI | Planned | GET,POST /product-attributes&lt;br&gt;GET,PATCH /product-attributes/{id} |
| ProductImageSetsBackendApi | BackendAPI | Planned | GET /concrete-product-image-sets |
| ProductPackagingUnitsBackendApi | Extension-Only BackendAPI | Planned | PickingListsBackendApi |
| ProductsBackendApi | BackendAPI | Planned | GET,POST /product-abstract&lt;br&gt;DELETE,GET,PATCH /product-abstract/{id} |
| PushNotificationsBackendApi | BackendAPI | Planned | GET,POST /push-notification-providers&lt;br&gt;PATCH,DELETE /push-notification-providers/{id}&lt;br&gt;POST /push-notification-subscriptions |
| SalesOrdersBackendApi | BackendAPI | Planned | GET /sales-orders |
| ServicePointsBackendApi | BackendAPI | Planned | GET,POST /service-points&lt;br&gt;GET,PATCH /service-points/{id}&lt;br&gt;GET,POST /service-point-addresses&lt;br&gt;PATCH /service-points/{id}/service-point-addresses/{id}&lt;br&gt;GET,POST /service-types&lt;br&gt;GET,PATCH /service-types/{id}&lt;br&gt;GET,POST /services&lt;br&gt;GET,PATCH /services/{id} |
| ShipmentTypesBackendApi | BackendAPI | Planned | GET,POST /shipment-types&lt;br&gt;GET,PATCH /shipment-types/{id} |
| ShipmentsBackendApi | BackendAPI | Planned | GET /sales-shipments |
| StoresBackendApi | BackendAPI | Planned | GET,POST,PATCH /stores |
| UsersBackendApi | BackendAPI | Planned | GET /users |
| WarehouseOauthBackendApi | BackendAPI | Planned | POST /warehouse-tokens |
| WarehouseUsersBackendApi | BackendAPI | Planned | GET,POST /warehouse-user-assignments&lt;br&gt;GET,PATCH,DELETE /warehouse-user-assignments/{id} |
| WarehousesBackendApi | BackendAPI | Planned | GET /warehouses |
</description>
            <pubDate>Wed, 06 May 2026 11:34:35 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/architecture/api-platform/migrate-to-api-platform-status.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/architecture/api-platform/migrate-to-api-platform-status.html</guid>
            
            
        </item>
        
        <item>
            <title>Back Office Configuration Framework</title>
            <description>&lt;p&gt;The Back Office Configuration Framework is a structured approach to exposing business-relevant configuration options directly in the Spryker Back Office. Instead of defining configuration in code or YAML files that require redeployment, businesses can manage defined behaviors through structured UI pages. Developers define configuration options once in YAML, and the framework automatically renders them as configurable Back Office interfaces.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;business-problems-it-solves&quot;&gt;Business problems it solves&lt;/h2&gt;
&lt;p&gt;Managing configuration in traditional commerce platforms creates friction between technical and business teams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configuration changes require developer involvement, code modifications, and a full deployment cycle.&lt;/li&gt;
&lt;li&gt;Business teams depend on IT to adjust behaviors that are fundamentally business decisions.&lt;/li&gt;
&lt;li&gt;YAML and code-level configuration is inaccessible to non-technical stakeholders and prone to error.&lt;/li&gt;
&lt;li&gt;Each configuration change introduces risk, slows down operations, and increases the total cost of change.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Back Office Configuration Framework addresses these challenges by creating a clear, controlled boundary between what developers define and what business users can adjust.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;key-value-for-your-business&quot;&gt;Key value for your business&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Faster time to change&lt;/strong&gt;
Business users adjust configured behaviors directly in the Back Office. No code change, no pull request, no deployment required.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reduced operational risk&lt;/strong&gt;
Configuration is exposed through structured, validated UI pages. Business users work within defined options rather than editing raw configuration files.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer efficiency&lt;/strong&gt;
Developers define configuration options once in YAML. The framework handles rendering, validation, and persistence automatically, eliminating repetitive UI work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consistent experience&lt;/strong&gt;
All configuration pages follow the same structure and interaction patterns, making it easier for business users to navigate and manage settings across features.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Extensibility by design&lt;/strong&gt;
The framework supports both out of the box Spryker features and project-specific customizations, so teams can introduce new configurable behaviors without building new infrastructure.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;who-benefits-and-how&quot;&gt;Who benefits and how&lt;/h2&gt;
&lt;h3 id=&quot;for-business-leaders&quot;&gt;For business leaders&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lower cost of change&lt;/strong&gt;
Adjusting business behaviors no longer requires a development sprint or deployment window. Teams can respond to market conditions and business needs faster.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reduced dependency on IT&lt;/strong&gt;
Business teams gain direct control over selected configuration options without needing to involve developers for every adjustment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stable, governed configurability&lt;/strong&gt;
The framework exposes only explicitly defined options. Business users operate within guardrails set by the development team, reducing the risk of misconfiguration.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;for-product-and-commerce-teams&quot;&gt;For product and commerce teams&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Self-service configuration&lt;/strong&gt;
Manage feature behavior directly from the Back Office, using familiar UI patterns. No need to understand YAML syntax or request a deployment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Faster iteration&lt;/strong&gt;
Test different configurations, observe results, and adjust without waiting for a release cycle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Visibility into configurable options&lt;/strong&gt;
All available configuration options are surfaced in one place, making it easy to understand what can be changed and what the current settings are.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;for-developers-and-architects&quot;&gt;For developers and architects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define once, render automatically&lt;/strong&gt;
Declare configuration options in YAML. The framework generates the corresponding Back Office UI, saving significant development and maintenance effort.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Separation of concerns&lt;/strong&gt;
Configuration definition stays with the developer; configuration management becomes a business user activity. This boundary is enforced by the framework.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Standardized patterns&lt;/strong&gt;
Avoid building custom configuration UIs for each feature. The framework provides consistent infrastructure that all teams benefit from.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;key-capabilities&quot;&gt;Key capabilities&lt;/h2&gt;
&lt;h3 id=&quot;support-for-out-of-the-box-and-custom-features&quot;&gt;Support for out of the box and custom features&lt;/h3&gt;
&lt;p&gt;The framework supports configuration for existing Spryker out of the box features as well as project-specific customizations. Teams can use it to expose configuration options for both standard platform capabilities and bespoke features built for a specific project.&lt;/p&gt;
&lt;h3 id=&quot;structured-and-controlled-business-configurability&quot;&gt;Structured and controlled business configurability&lt;/h3&gt;
&lt;p&gt;Selected business-relevant configuration moves from code level to UI level without exposing low-level technical complexity. The developer controls which options are available, what values are valid, and how they are presented. The business user controls what value is set, within those defined parameters.&lt;/p&gt;
&lt;h3 id=&quot;out-of-the-box-implementations&quot;&gt;Out of the box implementations&lt;/h3&gt;
&lt;p&gt;The Back Office Configuration Framework ships with the following out of the box implementations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;B2B Product Availability Display&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The initial release ships with a configuration UI for B2B Product Availability Display. This implementation demonstrates the framework in a real-world use case, allowing business users to configure how product availability information is presented to B2B buyers directly from the Back Office.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Basic Shop Theme&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The second out of the box implementation provides a configuration UI for shop branding. Business Admins can set theme colors, logo URLs, and custom CSS for the Storefront, Back Office, and Merchant Portal without code changes or redeployment. For details, see &lt;a href=&quot;/docs/pbc/all/back-office/latest/base-shop/basic-shop-theme-feature-overview.html&quot;&gt;Basic Shop Theme feature overview&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The Back Office Configuration Framework follows a developer-first definition approach with a business-user-facing runtime experience:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer defines configuration options in YAML&lt;/strong&gt;
The developer declares the available configuration options, their data types, validation rules, and default values in a structured YAML definition.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Framework generates the Back Office UI&lt;/strong&gt;
The framework reads the YAML definition and automatically renders the corresponding configuration page in the Back Office, including form fields, labels, and validation feedback.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Business user manages configuration&lt;/strong&gt;
A Back Office user with appropriate permissions accesses the configuration page, adjusts the available options, and saves changes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Changes take effect without redeployment&lt;/strong&gt;
Configuration updates are stored and applied at runtime. No code changes or deployments are required.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;comparison-to-traditional-configuration-approaches&quot;&gt;Comparison to traditional configuration approaches&lt;/h2&gt;
&lt;h3 id=&quot;code-level-configuration&quot;&gt;Code-level configuration&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Traditional approach:&lt;/strong&gt; Configuration values are hardcoded or set in PHP configuration files. Changing a value requires a code change, review, and deployment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Back Office Configuration Framework:&lt;/strong&gt; Configuration values are managed in the Back Office UI. Changes take effect immediately, within the boundaries defined by the developer.&lt;/p&gt;
&lt;h3 id=&quot;yaml-based-configuration&quot;&gt;YAML-based configuration&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Traditional approach:&lt;/strong&gt; Configuration is declared in YAML files that are part of the codebase. Changing a value requires editing a file, committing the change, and triggering a deployment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Back Office Configuration Framework:&lt;/strong&gt; YAML is still used, but only by developers to define what options are available. Business users interact with the resulting UI, not with YAML directly.&lt;/p&gt;
&lt;h3 id=&quot;custom-configuration-uis&quot;&gt;Custom configuration UIs&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Traditional approach:&lt;/strong&gt; Each feature that requires business-user configuration needs a custom-built UI, resulting in inconsistent experiences and duplicated development effort.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Back Office Configuration Framework:&lt;/strong&gt; All configurable features share the same framework-generated UI infrastructure, reducing development effort and ensuring a consistent experience.&lt;/p&gt;
</description>
            <pubDate>Tue, 05 May 2026 12:01:25 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/back-office/latest/base-shop/backoffice-configuration-framework.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/back-office/latest/base-shop/backoffice-configuration-framework.html</guid>
            
            
        </item>
        
        <item>
            <title>Resource Schemas</title>
            <description>This document explains how to define API Platform resource schemas in Spryker.

## Schema file structure

API Platform uses YAML files to define resource schemas. Resource schemas describe the structure, operations, and behavior of your API resources.

### Schema location

Resource schemas must be placed in the `resources/api/{api-type}/` directory within your module:

```MARKDOWN
src/
├── Spryker/
│   └── {Module}/
│       └── resources/
│           └── api/
│               ├── storefront/
│               │   └── resource-name.resource.yml
│               └── backend/
│                   └── resource-name.resource.yml
├── SprykerFeature/
│   └── {Feature}/
│       └── resources/
│           └── api/
│               └── backend/
│                   └── resource-name.resource.yml
└── Pyz/
    └── Glue/
        └── {Module}/
            └── resources/
                └── api/
                    └── backend/
                        └── resource-name.resource.yml
```

## CodeBucket resources

API Platform supports CodeBucket-specific resource variants that are resolved at runtime based on the `APPLICATION_CODE_BUCKET` environment constant. This enables Code Bucket-specific API resources without requiring separate container compilations.

### CodeBucket schema file naming

Resource schemas follow the pattern: `{resource-name}.resource.yml`
Validation schemas follow the pattern: `{resource-name}.validation.yml`

CodeBuckets are specified inside the schema files, not in the filename.

```MARKDOWN
src/Pyz/Glue/Store/resources/api/backend/
├── stores.resource.yml              # Resource schema (CodeBucket variants defined inside)
└── stores.validation.yml            # Validation schema (CodeBucket variants defined inside)
```

### Generated class naming

The generator creates classes following the pattern: `{ResourceName}{CodeBucket}{ApiType}Resource`

| Schema File | CodeBucket (defined in file) | Generated Class | CODE_BUCKET Constant |
|-------------|------------------------------|----------------|---------------------|
| `stores.resource.yml` | None (base) | `StoresBackendResource` | Not present (base resource) |
| `stores.resource.yml` | EU | `StoresEUBackendResource` | `&apos;EU&apos;` |
| `stores.resource.yml` | AT | `StoresATBackendResource` | `&apos;AT&apos;` |

### How CodeBucket resolution works

1. **Schema definition**: Define CodeBucket variants inside schema files using `codeBucket: EU`
2. **Constant generation**: Generator adds `public const string CODE_BUCKET = &apos;EU&apos;;` to variant classes
3. **Runtime resolution**: System reads `APPLICATION_CODE_BUCKET` and selects matching resource class
4. **Graceful fallback**: If no matching variant exists, base resource is used

### URL consistency

All CodeBucket variants share the same URL path, with the Code Bucket defined in the domain:

- EU variant: `glue-backend.eu.spryker.local/stores` → `StoresEUBackendResource`
- AT variant: `glue-backend.at.spryker.local/stores` → `StoresATBackendResource`
- DE variant: `glue-backend.de.spryker.local/stores` → `StoresBackendResource` (or `StoresDEBackendResource` if variant exists)

The URL path is identical (`/stores`), but the Code Bucket in the domain determines which resource variant is used. Only properties, validations, and business logic differ between variants.

### When to use CodeBucket resources

Use CodeBucket variants when you need:
- Code Bucket-specific properties (EU GDPR fields, tax rates)
- Code Bucket-specific validation rules
- Country-specific business logic
- Feature variations per Code Bucket

For a comprehensive guide including implementation examples, see [CodeBucket Support](/docs/dg/dev/architecture/api-platform/code-buckets.html).

## Resource schema syntax

### Minimal example

```yaml
resource:
  name: Products
  shortName: Product
  description: &quot;Product resource&quot;

  operations:
    - type: Get
    - type: GetCollection

  properties:
    id:
      type: integer
      writable: false
      identifier: true

    name:
      type: string
```

### Complete example with all options

```yaml
# yaml-language-server: $schema=../../../../SprykerSdk/Api/resources/schemas/api-resource-schema-v1.json

resource:
  # Resource identification
  name: Customers                    # Internal name (used for schema merging)
  shortName: Customer                # URL name (becomes /customers)
  description: &quot;Customer resource&quot;   # OpenAPI description

  # State providers and processors
  provider: &quot;Pyz\\Glue\\Customer\\Api\\Backend\\Provider\\CustomerBackendProvider&quot;
  processor: &quot;Pyz\\Glue\\Customer\\Api\\Backend\\Processor\\CustomerBackendProcessor&quot;

  # Pagination configuration
  paginationEnabled: true
  paginationItemsPerPage: 10
  paginationMaximumItemsPerPage: 100
  paginationClientEnabled: true
  paginationClientItemsPerPage: true

  # Security
  security: &quot;is_granted(&apos;ROLE_ADMIN&apos;)&quot;
  securityPostDenormalize: &quot;is_granted(&apos;EDIT&apos;, object)&quot;

  # Operations
  operations:
    - type: Post                     # Create new resource
    - type: Get                      # Get single resource
    - type: GetCollection            # Get collection with pagination
    - type: Put                      # Replace entire resource
    - type: Patch                    # Update partial resource
    - type: Delete                   # Delete resource

  # Properties
  properties:
    idCustomer:
      type: integer
      description: &quot;The unique identifier of the customer.&quot;
      writable: false                # Read-only property
      readable: true                 # Include in responses (default: true)

    email:
      type: string
      description: &quot;The email address.&quot;
      required: true                 # Required for all operations
      openapiContext:
        example: &quot;john@example.com&quot;
        format: &quot;email&quot;

    firstName:
      type: string
      description: &quot;First name.&quot;
      openapiContext:
        example: &quot;John&quot;
        minLength: 1
        maxLength: 100

    status:
      type: string
      description: &quot;Customer status.&quot;
      openapiContext:
        example: &quot;active&quot;
        schema:
          enum: [&quot;active&quot;, &quot;inactive&quot;, &quot;pending&quot;]

    customerReference:
      type: string
      description: &quot;Unique customer reference.&quot;
      writable: false
      identifier: true               # Use as URL identifier instead of @id

    dateOfBirth:
      type: string
      description: &quot;Date of birth.&quot;
      openapiContext:
        format: &quot;date&quot;
        example: &quot;1990-01-01&quot;

    isActive:
      type: boolean
      description: &quot;Active status.&quot;
      default: true

    creditLimit:
      type: number
      description: &quot;Credit limit.&quot;
      openapiContext:
        format: &quot;float&quot;
        example: 5000.00
```

## Property types

### Supported types

| Type | PHP Type | Example | Description |
|------|----------|---------|-------------|
| `string` | `string` | `&quot;John&quot;` | Text values |
| `integer` | `int` | `42` | Whole numbers |
| `number` | `float` | `3.14` | Decimal numbers |
| `boolean` | `bool` | `true` | True/false values |
| `array` | `array` | `[&quot;a&quot;, &quot;b&quot;]` | Lists of values |
| `object` | `object` | `{&quot;key&quot;: &quot;value&quot;}` | Strictly typed nested objects |
| `map` | `array` | `{&quot;key&quot;: &quot;value&quot;}` | Free-shape associative payloads documented via `openapiContext`. Stored as PHP `array` and rendered as `type: object` in the OpenAPI specification. |
| `mixed` | `mixed` | any | Use only when the payload genuinely has no fixed shape and cannot be described via `openapiContext`. |

Use `map` when the payload is a structured JSON object whose schema you want to describe via
`openapiContext` rather than a strongly typed PHP class. This is the recommended type whenever a
request or response body is a JSON object with a known shape but no dedicated DTO class — it
keeps the property typed as a simple `array` in PHP while still producing rich OpenAPI metadata
and a working &quot;Try Out&quot; body in Swagger UI. See
[Documenting nested properties for OpenAPI and Swagger UI](#documenting-nested-properties-for-openapi-and-swagger-ui)
for the full pattern.

### Property attributes

#### writable

Controls if property can be sent in requests (POST/PUT/PATCH):

```yaml
password:
  type: string
  writable: true    # Can be sent in requests
  readable: false   # Not included in responses
```

#### readable

Controls if property is included in responses:

```yaml
idCustomer:
  type: integer
  writable: false   # Cannot be modified
  readable: true    # Included in responses
```

#### identifier

Marks property as URL identifier:

```yaml
customerReference:
  type: string
  identifier: true  # URL becomes /customers/{customerReference}
```

#### required

Makes property mandatory (use validation schemas for detailed rules):

```yaml
email:
  type: string
  required: true    # Must be present
```

#### default

Sets default value:

```yaml
isActive:
  type: boolean
  default: true     # Defaults to true if not provided
```

## Documenting nested properties for OpenAPI and Swagger UI

Many endpoints accept or return structured JSON payloads — for example, a payment initialization
request that takes `payment`, `quote`, and `customer` sub-objects. Without explicit metadata,
those payloads appear as opaque `object` entries in the OpenAPI document, which means:

- The generated OpenAPI specification does not describe the child fields, their types, or which
  ones are required.
- The Swagger UI &quot;Try Out&quot; button shows an empty request body, forcing consumers to read code or
  external documentation to discover the expected shape.

The `map` property type combined with nested `openapiContext` entries closes both gaps.

### When to use this pattern

Use this pattern when the request or response body is a structured JSON object whose schema you
want to publish through OpenAPI, but you do not want to introduce a dedicated typed PHP class
for it. Typical cases are:

- Request payloads that aggregate fields from multiple transfer objects (for example, payment
  selection plus quote context).
- PSP- or provider-specific response payloads whose shape varies by configuration.

For payloads with a stable, strongly typed shape, prefer `type: object` so the generated PHP
class enforces the structure at the language level.

### Pattern

Combine `type: map` on the property with the following entries inside `openapiContext`:

| Entry | Purpose |
|-------|---------|
| `properties` | Declares each child field with its own `type`, `description`, `format`, and `example`. Used by Swagger UI to render the field-by-field schema. |
| `required` | Lists the child fields that must be present on a request. Drives the &quot;required&quot; markers in Swagger UI and the OpenAPI specification. |
| `example` | A complete sample payload. This is the value Swagger UI prefills into the &quot;Try Out&quot; body, so consumers can execute the request immediately. |

When the property is a `map`, the generator merges `&apos;type&apos; =&gt; &apos;object&apos;` into the emitted
`openapiContext`, so the property appears as an object — with the documented schema — in the
OpenAPI document while staying as a plain PHP `array` in the generated resource class.

### Worked example

The following extract is taken from
`src/Spryker/PaymentsRestApi/resources/api/storefront/payments.resource.yml`. It shows three
common shapes: a flat request object (`payment`), a request object with nested object children
(`quote`), and a response-only object whose contents vary at runtime (`preOrderPaymentData`).

```yaml
properties:
    payment:
        type: map
        writable: true
        readable: false
        required: true
        description: &apos;Payment selection for the pre-order initialization&apos;
        openapiContext:
            required: [&apos;paymentProviderName&apos;, &apos;paymentMethodName&apos;, &apos;amount&apos;]
            properties:
                paymentProviderName:
                    type: string
                    example: &apos;DummyPayment&apos;
                paymentMethodName:
                    type: string
                    example: &apos;Invoice&apos;
                amount:
                    type: integer
                    description: &apos;Amount in minor units (cents)&apos;
                    example: 9999
            example:
                paymentProviderName: &apos;DummyPayment&apos;
                paymentMethodName: &apos;Invoice&apos;
                amount: 9999

    quote:
        type: map
        writable: true
        readable: false
        required: true
        description: &apos;Quote context required to initialize the payment&apos;
        openapiContext:
            required: [&apos;customer&apos;, &apos;billingAddress&apos;, &apos;currency&apos;]
            properties:
                customer:
                    type: object
                    required: [&apos;firstName&apos;, &apos;lastName&apos;, &apos;email&apos;]
                    properties:
                        firstName: { type: string, example: &apos;Sonia&apos; }
                        lastName: { type: string, example: &apos;Wagner&apos; }
                        email: { type: string, format: email, example: &apos;sonia@acme.com&apos; }
                billingAddress:
                    type: object
                    required: [&apos;iso2Code&apos;]
                    properties:
                        iso2Code: { type: string, example: &apos;DE&apos; }
                currency:
                    type: object
                    required: [&apos;code&apos;]
                    properties:
                        code: { type: string, example: &apos;EUR&apos; }
            example:
                customer:
                    firstName: &apos;Sonia&apos;
                    lastName: &apos;Wagner&apos;
                    email: &apos;sonia@acme.com&apos;
                billingAddress:
                    iso2Code: &apos;DE&apos;
                currency:
                    code: &apos;EUR&apos;

    preOrderPaymentData:
        type: map
        writable: false
        readable: true
        required: false
        description: &apos;PSP-specific response payload returned by the payment provider&apos;
        openapiContext:
            example:
                transactionId: &apos;tx_abc123&apos;
                redirectUrl: &apos;https://psp.example.com/pay/tx_abc123&apos;
```

### Read-only versus write-only payloads

- **Write-only request payloads** (`writable: true`, `readable: false`) should declare
  `properties`, `required`, and `example`. The first two drive request validation and the
  generated OpenAPI schema; `example` makes the Swagger UI &quot;Try Out&quot; body usable without
  edits.
- **Read-only response payloads** (`writable: false`, `readable: true`) only need
  `openapiContext.example` when the response shape is dynamic. If the response shape is fixed,
  prefer declaring `properties` (and optionally `required`) so consumers see the full schema.

### Validation note

`openapiContext.required` controls only the OpenAPI documentation. If a request field must be
enforced at runtime, add the matching constraint to the resource&apos;s validation schema — see
[Validation Schemas](/docs/dg/dev/architecture/api-platform/validation-schemas.html).

## Operations

Define which HTTP operations are available for the resource:

```yaml
operations:
  - type: Get                      # GET /customers/{id}
  - type: GetCollection            # GET /customers
  - type: Post                     # POST /customers
  - type: Put                      # PUT /customers/{id}
  - type: Patch                    # PATCH /customers/{id}
  - type: Delete                   # DELETE /customers/{id}
```

The operation names map to HTTP methods:
- `post` → POST (create)
- `get` → GET (single resource)
- `getCollection` → GET (collection)
- `put` → PUT (replace)
- `patch` → PATCH (update)
- `delete` → DELETE (remove)

## Pagination

API Platform provides built-in pagination for collection endpoints (`GetCollection`). You can configure pagination behavior per resource using YAML schema options.

### Pagination options

| Option | Type | Description |
|--------|------|-------------|
| `paginationEnabled` | `boolean` | Enables or disables pagination for this resource. When `false`, `GetCollection` returns all results without pagination. Default: inherits from global configuration. |
| `paginationItemsPerPage` | `integer` | Number of items returned per page. Overrides the global default. |
| `paginationMaximumItemsPerPage` | `integer` | Maximum number of items a client can request per page via `itemsPerPage` query parameter. Prevents clients from requesting excessively large pages. |
| `paginationClientEnabled` | `boolean` | Allows clients to enable or disable pagination via the `pagination` query parameter (for example, `?pagination=false`). |
| `paginationClientItemsPerPage` | `boolean` | Allows clients to set the number of items per page via the `itemsPerPage` query parameter (for example, `?itemsPerPage=50`). |

The global default for `paginationItemsPerPage` is defined in the project&apos;s `api_platform.php` configuration file. To override it for a specific resource, set `paginationItemsPerPage` in the resource schema.

### Minimal pagination example

```yaml
resource:
  name: Products
  shortName: products

  paginationEnabled: true
  paginationItemsPerPage: 10

  operations:
    - type: GetCollection
```

### Full pagination example

```yaml
resource:
  name: Products
  shortName: products

  paginationEnabled: true
  paginationItemsPerPage: 20
  paginationMaximumItemsPerPage: 100
  paginationClientEnabled: true
  paginationClientItemsPerPage: true

  operations:
    - type: GetCollection
    - type: Get
```

With this configuration, clients can use the following query parameters:

```bash
# Default pagination (20 items per page)
GET /products

# Navigate to page 3
GET /products?page=3

# Request 50 items per page (up to maximum of 100)
GET /products?itemsPerPage=50

# Disable pagination to get all results
GET /products?pagination=false
```

### Generated output

The pagination options are rendered as named parameters in the `#[ApiResource]` attribute:

```php
#[ApiResource(
    operations: [new GetCollection(), new Get()],
    shortName: &apos;products&apos;,
    provider: ProductsBackendProvider::class,
    paginationItemsPerPage: 20,
    paginationEnabled: true,
    paginationMaximumItemsPerPage: 100,
    paginationClientEnabled: true,
    paginationClientItemsPerPage: true
)]
```

### Provider requirements

For pagination to work, your Provider must return a `TraversablePaginator` instance for collection operations:

```php
use ApiPlatform\State\Pagination\TraversablePaginator;

return new TraversablePaginator(
    new \ArrayObject($resources),
    $currentPage,
    $itemsPerPage,
    $totalItems
);
```

If `paginationEnabled` is `true` but the Provider returns a plain array, API Platform wraps the result in a `PartialPaginatorInterface`, which may not include total count or page metadata.

### Global pagination defaults

Global pagination defaults can be configured in the application configuration file. Per-resource settings override the global defaults. See [API Platform Configuration](/docs/dg/dev/architecture/api-platform/configuration.html) for details.

## Relationships

Define relationships between resources to enable including related resources via the `?include=` query parameter.

### includes section

Declares what relationships this resource can include:

```yaml
includes:
  - relationshipName: addresses
    targetResource: CustomersAddresses
    uriVariableMappings:
      customerReference: customerReference
```

**Properties:**
- `relationshipName`: Name used in `?include=` parameter
- `targetResource`: Name of the resource to include
- `uriVariableMappings`: Maps properties from parent to child provider

### includableIn section

Declares where this resource can be included:

```yaml
includableIn:
  - resource: Customers
    relationshipName: addresses
    uriVariableMappings:
      customerReference: customerReference
```

Both declarations must match for validation to pass.

For detailed information about relationships, see [Relationships](/docs/dg/dev/architecture/api-platform/relationships.html).

## Resource generation process

### Generation workflow

The resource generation process is organized into distinct phases, each producing result objects for comprehensive error tracking and reporting:

```MARKDOWN
1. Preparation Phase
   ↓
2. Schema Parsing Phase → ParseResult
   - Load validation schemas
   - Parse validation rules
   - Load resource schemas
   - Parse resource definitions
   ↓
3. Schema Merging Phase → MergeResult
   - Merge schemas (Core → Feature → Project)
   - Track contributing source files
   ↓
4. Validation Phase → ValidationResult
   - Validate merged schemas
   - Apply validation rules
   ↓
5. Code Generation Phase
   - Generate PHP resource classes
   - Write files to output directory
   ↓
6. Cache Update
```

### Result objects

Each phase produces result objects that encapsulate both successful outcomes and failures:

- **ParseResult**: Contains grouped schemas and tracks failed validation files and schema files that could not be parsed
- **MergeResult**: Contains successfully merged schemas and tracks resources that failed to merge
- **ValidationResult**: Contains validated schemas and tracks resources that failed validation with detailed error messages

This structured approach ensures that errors in one resource do not block the generation of other valid resources, and provides clear feedback about what succeeded and what failed.

### Multi-layer schema merging

Spryker automatically merges schemas from multiple layers:

**Core layer** (lowest priority):

**vendor/spryker/customer/resources/api/backend/customer.resource.yml**

```yaml
resource:
  name: Customers
  properties:
    email:
      type: string
    firstName:
      type: string
```

**Feature layer** (medium priority):

**src/SprykerFeature/CRM/resources/api/backend/customer.resource.yml**

```yaml
resource:
  name: Customers
  properties:
    phone:
      type: string      # Added property
```

**Project layer** (highest priority):

**src/Pyz/Glue/Customer/resources/api/backend/customer.resource.yml**

```yaml
resource:
  name: Customers
  properties:
    email:
      required: true    # Override core definition
    customField:
      type: string      # Project-specific field
```

**Merged result:**

```yaml
resource:
  name: Customers
  properties:
    email:
      type: string
      required: true    # From project layer
    firstName:
      type: string      # From core layer
    phone:
      type: string      # From feature layer
    customField:
      type: string      # From project layer
```

### Generated resource class

The generator creates a complete PHP class with API Platform attributes:

```php
&lt;?php

declare(strict_types=1);
namespace Generated\Api\Backend;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\ApiProperty;
use Symfony\Component\Validator\Constraints as Assert;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Delete;

#[ApiResource(
    operations: [new Post(), new Get(), new GetCollection(), new Patch(), new Delete()],
    shortName: &apos;Customer&apos;,
    provider: CustomerBackendProvider::class,
    processor: CustomerBackendProcessor::class,
    paginationItemsPerPage: 10,
    paginationEnabled: true,
    paginationMaximumItemsPerPage: 100,
    paginationClientEnabled: true,
    paginationClientItemsPerPage: true
)]
final class CustomersBackendResource
{
    #[ApiProperty(writable: false)]
    public ?int $idCustomer = null;

    #[ApiProperty(openapiContext: [&apos;example&apos; =&gt; &apos;john@example.com&apos;])]
    #[Assert\NotBlank(groups: [&apos;customers:create&apos;])]
    #[Assert\Email(groups: [&apos;customers:create&apos;])]
    public ?string $email = null;

    #[ApiProperty(identifier: true, writable: false)]
    public ?string $customerReference = null;

    public ?bool $isActive = true;

    // Getters, setters, toArray(), fromArray() methods...
}
```

## Debugging schemas

### Debug commands

```bash
# List all resources
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:debug --list

# Show specific resource
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:debug customers --api-type=backend

# Show merged schema
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:debug customers --api-type=backend --show-merged

# Show contributing source files
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:debug customers --api-type=backend --show-sources

# Validate schemas without generating
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate --validate-only
```

### Common schema errors

The generator validates schemas and provides detailed error messages:

```bash
# Missing required fields
Error: Resource &quot;customers&quot; is missing required field &quot;name&quot;

# Invalid operation type
Error: Invalid operation type &quot;INVALID&quot;. Must be one of: Get, Post, Put, Patch, Delete, GetCollection

# Invalid property type
Error: Property &quot;age&quot; has invalid type &quot;int&quot;. Must be one of: string, integer, number, boolean, array, object

# Provider class not found
Error: Provider class &quot;Pyz\Glue\Customer\Api\Backend\Provider\MissingProvider&quot; does not exist
```

## Advanced schema features

### Custom URL paths

Operations support `uriTemplate` and `uriVariables` to define custom URL paths, including sub-resource URLs like `/customers/{customerReference}/addresses`.

#### Sub-resource with full CRUD

Define a child resource with nested URLs by adding `uriTemplate` and `uriVariables` to each operation:

**customers-addresses.resource.yml**

```yaml
resource:
  name: CustomersAddresses
  shortName: customers-addresses

  operations:
    - type: GetCollection
      uriTemplate: &apos;/customers/{customerReference}/addresses&apos;
      uriVariables:
        customerReference:
          toProperty: &apos;customer&apos;
          fromClass: CustomersStorefrontResource

    - type: Get
      uriTemplate: &apos;/customers/{customerReference}/addresses/{uuid}&apos;
      uriVariables:
        customerReference:
          toProperty: &apos;customer&apos;
          fromClass: CustomersStorefrontResource
        uuid:
          fromClass: CustomersAddressesStorefrontResource

    - type: Post
      uriTemplate: &apos;/customers/{customerReference}/addresses&apos;
      uriVariables:
        customerReference:
          toProperty: &apos;customer&apos;
          fromClass: CustomersStorefrontResource
```

**`uriVariables` properties:**
- `fromClass`: The generated resource class the variable originates from
- `toProperty`: The property on the current resource that links to the parent resource

#### Action-style sub-resource

For single-action endpoints nested under a parent resource:

**customers-confirm-registration.resource.yml**

```yaml
resource:
  name: CustomersConfirmRegistration
  shortName: customers-confirm-registration

  operations:
    - type: Post
      uriTemplate: /customers/{customerReference}/confirm-registration
```

For more details on `uriTemplate`, `uriVariables`, and sub-resource patterns, see the [API Platform sub-resources documentation](https://api-platform.com/docs/core/subresources/).

### Security expressions

Security expressions protect resources and operations using [Symfony&apos;s ExpressionLanguage](https://symfony.com/doc/current/security/expressions.html). They require the SecurityBundle to be configured. See [How to integrate API Platform Security](/docs/dg/dev/upgrade-and-migrate/integrate-api-platform-security.html) for setup instructions.

{% info_block infoBox &quot;Where roles come from&quot; %}

Roles like `ROLE_CUSTOMER` in security expressions come from OAuth scopes that are automatically mapped to Symfony roles. The mapping convention is as follows: a scope name is uppercased and prefixed with `ROLE_`. For example, the `customer` scope becomes `ROLE_CUSTOMER`.

Scopes are provided by scope provider plugins registered in `OauthDependencyProvider::getScopeProviderPlugins()`. The following table lists the out-of-the-box scope provider plugins and the scopes they provide:

| Plugin | Scopes |
|--------|--------|
| `CustomerOauthScopeProviderPlugin` | `customer` |
| `CompanyUserOauthScopeProviderPlugin` | `company_user` |
| `AgentOauthScopeProviderPlugin` | `agent` |
| `CustomerImpersonationOauthScopeProviderPlugin` | `customer_impersonation`, `customer` |
| `UserOauthScopeProviderPlugin` | `user`, plus UserType sub-plugins |
| `WarehouseOauthScopeProviderPlugin` | `warehouse` |

For details on how the mapping works, see [Security — Roles and OAuth scope mapping](/docs/dg/dev/architecture/api-platform/security.html). For instructions on setting up scopes, see [Integrate the authorization scopes](/docs/integrations/spryker-glue-api/backend-api/integrate-backend-api/integrate-the-authorization-scopes.html).

{% endinfo_block %}

Three types of security expressions are supported:

| Expression | Evaluated | Use case | When to use |
|-----------|-----------|----------|-------------|
| `security` | Before the request is processed | Check user roles or authentication status | For role or authentication checks that do not depend on the request body. |
| `securityPostDenormalize` | After the request body is deserialized | Check authorization based on submitted data | When authorization depends on the deserialized resource `object`, for example, to verify the user owns the resource being modified. |
| `securityPostValidation` | After validation passes | Check authorization based on validated data | When authorization depends on validated data, for example, to verify a value is within the user&apos;s authorized limit after validation confirms the data is structurally correct. |

#### Resource-level security

Applies to all operations on the resource:

```yaml
resource:
  name: Customers
  shortName: customers
  security: &quot;is_granted(&apos;ROLE_USER&apos;)&quot;
```

#### Operation-level security

Applies to a specific operation, overriding resource-level security:

```yaml
resource:
  name: Customers
  shortName: customers

  operations:
    - type: Post
      # No security — public registration

    - type: Get
      security: &quot;is_granted(&apos;ROLE_USER&apos;)&quot;

    - type: Patch
      security: &quot;is_granted(&apos;ROLE_USER&apos;)&quot;
```

#### Post-denormalize security

Evaluated after the request body has been deserialized. The `object` variable contains the resource instance:

```yaml
resource:
  name: Orders
  shortName: orders
  security: &quot;is_granted(&apos;ROLE_USER&apos;)&quot;
  securityPostDenormalize: &quot;is_granted(&apos;EDIT&apos;, object)&quot;
```

{% info_block infoBox &quot;Custom voter attributes&quot; %}

`EDIT` in the example is a **custom voter attribute** — it is an application-defined string, not a built-in Symfony or Spryker constant. For `is_granted(&apos;EDIT&apos;, object)` to work, you must register a custom Symfony [Voter](https://symfony.com/doc/current/security/voters.html) that supports the `EDIT` attribute and implements the authorization logic, for example, checking that the authenticated user owns the resource.

Use `securityPostDenormalize` when the authorization decision depends on the **submitted request data** (the deserialized `object`), such as verifying resource ownership.

{% endinfo_block %}

#### Post-validation security

Evaluated after validation has passed:

```yaml
resource:
  name: Payments
  shortName: payments
  securityPostValidation: &quot;is_granted(&apos;PROCESS&apos;, object)&quot;
```

{% info_block infoBox &quot;Custom voter attributes&quot; %}

`PROCESS` in the example is a **custom voter attribute** — it is an application-defined string, not a built-in Symfony or Spryker constant. For `is_granted(&apos;PROCESS&apos;, object)` to work, you must register a custom Symfony [Voter](https://symfony.com/doc/current/security/voters.html) that supports the `PROCESS` attribute.

Use `securityPostValidation` when the authorization decision depends on **validated data**, for example, to verify a payment amount is within the user&apos;s authorized limit after validation confirms the data is structurally correct.

{% endinfo_block %}

For detailed information about the authentication flow, role mapping, and accessing the authenticated user in providers, see [Security](/docs/dg/dev/architecture/api-platform/security.html).

## Generation commands

### Basic generation

```bash
# Generate all configured API types
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate

# Generate specific API type
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate backend
docker/sdk cli GLUE_APPLICATION=GLUE_STOREFRONT glue api:generate storefront

# Generate with options
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate --dry-run           # Preview without writing
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate --validate-only     # Only validate schemas
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate --resource=customers  # Generate single resource
```

### Output

```bash
Generating API resources for ApiType: backend

Discovering schema files...
Validating schemas... OK
Merging schemas... OK

Generating resources:
 10/10 [============================] 100%

Generated: 10 file(s)
Cache updated

Done!
```

## Schema validation rules

The generator enforces these rules:

### Required fields

Every resource must have:
- `name` - Internal resource name
- `shortName` - URL-friendly name
- At least one `operation`
- At least one `property`

### Valid operation types

Only these operation types are allowed:
- `Get` - Retrieve single resource
- `GetCollection` - Retrieve collection
- `Post` - Create resource
- `Put` - Replace entire resource
- `Patch` - Update partial resource
- `Delete` - Delete resource

### Valid property types

Only these property types are allowed:
- `string`
- `integer`
- `number`
- `boolean`
- `array`
- `object`
- `map`
- `mixed`

### Provider/Processor validation

- Provider/Processor classes must exist
- Classes must implement correct interfaces
- Namespaces must be valid PHP namespaces

## Best practices

### 1. Use semantic naming

```yaml
# ✅ Good
resource:
  name: Customers
  shortName: Customer

# ❌ Bad
resource:
  name: CustomerData
  shortName: cust
```

### 2. Document all properties

```yaml
# ✅ Good
email:
  type: string
  description: &quot;The customer&apos;s email address used for login and notifications&quot;

# ❌ Bad
email:
  type: string
```

### 3. Leverage schema merging

Core — define base properties:

**src/Spryker/Customer/resources/api/backend/customer.resource.yml**

```yaml
resource:
  name: Customers
  properties:
    email:
      type: string
```

Project — only override what is needed:

**src/Pyz/Glue/Customer/resources/api/backend/customer.resource.yml**

```yaml
resource:
  name: Customers
  properties:
    email:
      required: true  # ← Only the difference
```

### 4. Use readable/writable correctly

```yaml
# Read-only fields (IDs, timestamps)
idCustomer:
  type: integer
  writable: false

# Write-only fields (passwords)
password:
  type: string
  readable: false

# Read-write fields (normal data)
email:
  type: string
  writable: true
  readable: true
```

## Next steps

- [API Platform](/docs/dg/dev/architecture/api-platform.html) - Architecture overview
- [Validation Schemas](/docs/dg/dev/architecture/api-platform/validation-schemas.html) - Define validation rules
- [CodeBucket Support](/docs/dg/dev/architecture/api-platform/code-buckets.html) - Code Bucket-specific resources
- [API Platform Enablement](/docs/dg/dev/architecture/api-platform/enablement.html) - Creating resources
- [API Platform Testing](/docs/dg/dev/architecture/api-platform/testing.html) - Writing and running tests
- [Troubleshooting](/docs/dg/dev/architecture/api-platform/troubleshooting.html) - Common issues
- [API Platform Documentation](https://api-platform.com/docs/) - Official API Platform docs
</description>
            <pubDate>Tue, 05 May 2026 07:54:35 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/architecture/api-platform/resource-schemas.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/architecture/api-platform/resource-schemas.html</guid>
            
            
        </item>
        
        <item>
            <title>Install the Product Attribute Visibility feature</title>
            <description>This document describes how to install the [Product Attribute Visibility feature](/docs/pbc/all/product-information-management/latest/base-shop/feature-overviews/product-feature-overview/product-attribute-visibility-overview.html).

## Prerequisites

### Install the required features

| NAME | VERSION | INSTALLATION GUIDE |
| --- | --- | --- |
| Spryker Core | {{page.release_tag}} | [Install the Spryker Core feature](/docs/pbc/all/miscellaneous/latest/install-and-upgrade/install-features/install-the-spryker-core-feature.html) |
| Product | {{page.release_tag}} | [Install the Product feature](/docs/pbc/all/product-information-management/latest/base-shop/install-and-upgrade/install-features/install-the-product-feature.html) |

### Install the required packages

| PACKAGE | VERSION |
| --- | --- |
| spryker-feature/product-experience-management | ^2.2.0 |
| spryker/product-attribute | ^1.20.0 |
| spryker/product-attribute-extension | ^1.2.0 |
| spryker/product-attribute-gui | ^2.3.0 |
| spryker/product-attribute-gui-extension | ^1.0.0 |
| spryker/product-management | ^0.20.8 |
| spryker-shop/cart-page | ^3.58.0 |
| spryker-shop/catalog-page | ^1.36.0 |
| spryker-shop/product-detail-page | ^3.31.0 |
| spryker-shop/product-widget | ^1.6.0 |
| spryker-shop/shop-ui | ^1.106.0 |

```bash
composer require spryker/product-attribute:&quot;^1.20.0&quot; spryker/product-attribute-extension:&quot;^1.2.0&quot; spryker/product-attribute-gui:&quot;^2.3.0&quot; spryker/product-attribute-gui-extension:&quot;^1.0.0&quot; spryker-feature/product-experience-management:&quot;^2.2.0&quot; spryker/product-management:&quot;^0.20.8&quot; spryker-shop/cart-page:&quot;^3.58.0&quot; spryker-shop/catalog-page:&quot;^1.36.0&quot; spryker-shop/product-detail-page:&quot;^3.31.0&quot; spryker-shop/product-widget:&quot;^1.6.0&quot; spryker-shop/shop-ui:&quot;^1.106.0&quot; --update-with-dependencies --ignore-platform-req=ext-grpc
```

## 1) Set up configuration

Set up RabbitMQ and Symfony Messenger configuration for the publish and sync queues.

**src/Pyz/Client/RabbitMq/RabbitMqConfig.php**

```php
&lt;?php

namespace Pyz\Client\RabbitMq;

use SprykerFeature\Shared\ProductExperienceManagement\ProductExperienceManagementConfig;

class RabbitMqConfig extends SprykerRabbitMqConfig
{
    /**
     * @return list&lt;mixed&gt;
     */
    protected function getPublishQueueConfiguration(): array
    {
        return [
            ProductExperienceManagementConfig::PUBLISH_PRODUCT_ATTRIBUTE,
        ];
    }

    /**
     * @return list&lt;string&gt;
     */
    protected function getSynchronizationQueueConfiguration(): array
    {
        return [
            ProductExperienceManagementConfig::PRODUCT_ATTRIBUTE_SYNC_STORAGE_QUEUE,
        ];
    }
}
```

**src/Pyz/Zed/Queue/QueueDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Zed\Queue;

use SprykerFeature\Shared\ProductExperienceManagement\ProductExperienceManagementConfig;
use Spryker\Zed\Event\Communication\Plugin\Queue\EventQueueMessageProcessorPlugin;
use Spryker\Zed\Queue\QueueDependencyProvider as SprykerQueueDependencyProvider;
use Spryker\Zed\Synchronization\Communication\Plugin\Queue\SynchronizationStorageQueueMessageProcessorPlugin;

class QueueDependencyProvider extends SprykerQueueDependencyProvider
{
    /**
     * @return array&lt;string, \Spryker\Zed\Queue\Dependency\Plugin\QueueMessageProcessorPluginInterface&gt;
     */
    protected function getProcessorMessagePlugins(): array
    {
        return [
            ProductExperienceManagementConfig::PUBLISH_PRODUCT_ATTRIBUTE =&gt; new EventQueueMessageProcessorPlugin(),
            ProductExperienceManagementConfig::PRODUCT_ATTRIBUTE_SYNC_STORAGE_QUEUE =&gt; new SynchronizationStorageQueueMessageProcessorPlugin(),
        ];
    }
}
```

**src/Pyz/Client/SymfonyMessenger/SymfonyMessengerConfig.php**

```php
&lt;?php

namespace Pyz\Client\SymfonyMessenger;

use SprykerFeature\Shared\ProductExperienceManagement\ProductExperienceManagementConfig;

class SymfonyMessengerConfig extends SprykerSymfonyMessengerConfig
{
    /**
     * @return list&lt;mixed&gt;
     */
    protected function getPublishQueueConfiguration(): array
    {
        return [
            ProductExperienceManagementConfig::PUBLISH_PRODUCT_ATTRIBUTE,
        ];
    }

    /**
     * @return list&lt;string&gt;
     */
    protected function getSynchronizationQueueConfiguration(): array
    {
        return [
            ProductExperienceManagementConfig::PRODUCT_ATTRIBUTE_SYNC_STORAGE_QUEUE,
        ];
    }
}
```

### Optional: Extend visibility types

By default, the feature provides three visibility types: `PDP`, `PLP`, and `Cart`. To add project-specific visibility types, extend `ProductExperienceManagementConfig` at the project level and override the `getAvailableVisibilityTypes()` method.

**src/Pyz/Shared/ProductExperienceManagement/ProductExperienceManagementConfig.php**

```php
&lt;?php

namespace Pyz\Shared\ProductExperienceManagement;

use SprykerFeature\Shared\ProductExperienceManagement\ProductExperienceManagementConfig as SprykerProductExperienceManagementConfig;

class ProductExperienceManagementConfig extends SprykerProductExperienceManagementConfig
{
    /**
     * @var string
     */
    public const string VISIBILITY_TYPE_WISHLIST = &apos;Wishlist&apos;;

    /**
     * @return array&lt;string&gt;
     */
    public function getAvailableVisibilityTypes(): array
    {
        return array_merge(parent::getAvailableVisibilityTypes(), [
            static::VISIBILITY_TYPE_WISHLIST,
        ]);
    }
}
```

After adding a custom visibility type, implement the corresponding widget or template logic in your Yves layer to render the attribute on the relevant page.

## 2) Set up the database schema and transfer objects

1. Create the following schema file to enable event-driven publishing for product management attributes:

**src/Pyz/Zed/ProductAttribute/Persistence/Propel/Schema/spy_product_management_attribute.schema.xml**

```xml
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;database xmlns=&quot;spryker:schema-01&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; name=&quot;zed&quot; xsi:schemaLocation=&quot;spryker:schema-01 https://static.spryker.com/schema-01.xsd&quot; namespace=&quot;Orm\Zed\ProductAttribute\Persistence&quot; package=&quot;src.Orm.Zed.ProductAttribute.Persistence&quot;&gt;

    &lt;table name=&quot;spy_product_management_attribute&quot;&gt;
        &lt;behavior name=&quot;event&quot;&gt;
            &lt;parameter name=&quot;spy_product_management_attribute_all&quot; column=&quot;*&quot;/&gt;
        &lt;/behavior&gt;
    &lt;/table&gt;

&lt;/database&gt;
```

2. Apply database changes and generate entity and transfer changes:

```bash
console propel:install
console transfer:generate
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure that the following changes have been applied in the database:

| DATABASE ENTITY | TYPE | EVENT |
| --- | --- | --- |
| spy_product_management_attribute.visibility | column | created |
| spy_product_attribute_storage | table | created |

Make sure the following transfer objects have been generated:

| TRANSFER | TYPE | EVENT |
| --- | --- | --- |
| ProductAttributeStorage | class | created |
| ProductAttributeStorage.key | property | created |
| ProductAttributeStorage.inputType | property | created |
| ProductAttributeStorage.isSuper | property | created |
| ProductAttributeStorage.visibilityTypes | property | created |
| ProductManagementAttribute.visibility | property | created |
| ProductManagementAttribute.visibilityTypes | property | created |
| ProductManagementAttributeCollection | class | created |
| ProductManagementAttributeCriteria | class | created |
| ProductManagementAttributeConditions.productManagementAttributeIds | property | created |
| ProductAttributeTableCriteria | class | created |
| ProductAttributeTableCriteria.visibilityTypes | property | created |
| ProductAttributeTableCriteria.withColumns | property | created |
| ProductAttributeTableCriteria.queryConditions | property | created |
| ProductAttributeTableCriteria.conditionCombineOperator | property | created |
| ProductAttributeTableQueryCondition | class | created |
| ProductAttributeQueryCriteria | class | created |
| ProductAttributeQueryCriteria.withColumns | property | created |

{% endinfo_block %}

## 3) Set up behavior

### Set up publisher and synchronization plugins

Register the publisher and synchronization plugins:

| PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
| --- | --- | --- | --- |
| ProductAttributePublisherTriggerPlugin | Triggers a full publish of product attribute data. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\Publisher |
| ProductAttributeWritePublisherPlugin | Handles create and update events for product attributes and writes data to storage. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\Publisher |
| ProductAttributeSynchronizationDataBulkRepositoryPlugin | Provides product attribute storage data for the synchronization process. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\Synchronization |

**src/Pyz/Zed/Publisher/PublisherDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Zed\Publisher;

use SprykerFeature\Shared\ProductExperienceManagement\ProductExperienceManagementConfig;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\Publisher\ProductAttributePublisherTriggerPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\Publisher\ProductAttributeWritePublisherPlugin;
use Spryker\Zed\Publisher\PublisherDependencyProvider as SprykerPublisherDependencyProvider;

class PublisherDependencyProvider extends SprykerPublisherDependencyProvider
{
    /**
     * @return array&lt;string, list&lt;\Spryker\Zed\PublisherExtension\Dependency\Plugin\PublisherPluginInterface&gt;&gt;
     */
    protected function getPublisherPlugins(): array
    {
        return array_merge(
            parent::getPublisherPlugins(),
            $this-&gt;getProductAttributeStoragePlugins(),
        );
    }

    /**
     * @return list&lt;\Spryker\Zed\PublisherExtension\Dependency\Plugin\PublisherTriggerPluginInterface&gt;
     */
    protected function getPublisherTriggerPlugins(): array
    {
        return [
            new ProductAttributePublisherTriggerPlugin(),
        ];
    }

    /**
     * @return list&lt;\Spryker\Zed\PublisherExtension\Dependency\Plugin\PublisherPluginInterface&gt;
     */
    protected function getProductAttributeStoragePlugins(): array
    {
        return [
            ProductExperienceManagementConfig::PUBLISH_PRODUCT_ATTRIBUTE =&gt; [
                new ProductAttributeWritePublisherPlugin(),
            ],
        ];
    }
}
```

**src/Pyz/Zed/Synchronization/SynchronizationDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Zed\Synchronization;

use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\Synchronization\ProductAttributeSynchronizationDataBulkRepositoryPlugin;
use Spryker\Zed\Synchronization\SynchronizationDependencyProvider as SprykerSynchronizationDependencyProvider;

class SynchronizationDependencyProvider extends SprykerSynchronizationDependencyProvider
{
    /**
     * @return list&lt;\Spryker\Zed\SynchronizationExtension\Dependency\Plugin\SynchronizationDataPluginInterface&gt;
     */
    protected function getSynchronizationDataStorePlugins(): array
    {
        return [
            new ProductAttributeSynchronizationDataBulkRepositoryPlugin(),
        ];
    }
}
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure that when you create or update a product attribute in the Back Office, the attribute data is published and synchronized to the `spy_product_attribute_storage` table:

1. In the Back Office, go to **Catalog &gt; Attributes**.
2. Edit an attribute and change its **Display At** value.
3. Click **Save**.
4. Check that the `spy_product_attribute_storage` table contains the updated attribute data.

{% endinfo_block %}

### Set up product attribute query expander

Register the query expander plugin:

| PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
| --- | --- | --- | --- |
| VisibilityProductAttributeQueryExpanderPlugin | Expands the product attribute query with the visibility column. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttribute |
| VisibilitySuggestKeysQueryExpanderPlugin | Expands the suggest keys query with visibility filtering. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttribute |
| VisibilitySuggestKeysExpanderPlugin | Expands the suggest keys result with visibility data. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttribute |

**src/Pyz/Zed/ProductAttribute/ProductAttributeDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Zed\ProductAttribute;

use Spryker\Zed\ProductAttribute\ProductAttributeDependencyProvider as SprykerProductAttributeDependencyProvider;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttribute\VisibilityProductAttributeQueryExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttribute\VisibilitySuggestKeysExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttribute\VisibilitySuggestKeysQueryExpanderPlugin;

class ProductAttributeDependencyProvider extends SprykerProductAttributeDependencyProvider
{
    /**
     * @return list&lt;\Spryker\Zed\ProductAttributeExtension\Dependency\Plugin\ProductAttributeQueryExpanderPluginInterface&gt;
     */
    protected function getProductAttributeQueryExpanderPlugins(): array
    {
        return [
            new VisibilityProductAttributeQueryExpanderPlugin(),
        ];
    }

    /**
     * @return list&lt;\Spryker\Zed\ProductAttributeExtension\Dependency\Plugin\SuggestKeysQueryExpanderPluginInterface&gt;
     */
    protected function getSuggestKeysQueryExpanderPlugins(): array
    {
        return [
            new VisibilitySuggestKeysQueryExpanderPlugin(),
        ];
    }

    /**
     * @return list&lt;\Spryker\Zed\ProductAttributeExtension\Dependency\Plugin\SuggestKeysExpanderPluginInterface&gt;
     */
    protected function getSuggestKeysExpanderPlugins(): array
    {
        return [
            new VisibilitySuggestKeysExpanderPlugin(),
        ];
    }
}
```

### Set up Back Office attribute form and table plugins

Register the Back Office plugins for the attribute management UI:

| PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
| --- | --- | --- | --- |
| VisibilityAttributeTableConfigExpanderPlugin | Expands the attribute table configuration with the visibility column. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui |
| VisibilityAttributeTableHeaderExpanderPlugin | Adds the Display At header to the attribute table. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui |
| VisibilityAttributeTableDataExpanderPlugin | Renders visibility badges in attribute table rows. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui |
| VisibilityAttributeTableCriteriaExpanderPlugin | Adds visibility filter conditions to the attribute table query. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui |
| VisibilityAttributeFormExpanderPlugin | Adds the visibility types select field to the attribute form. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui |
| VisibilityAttributeFormDataProviderExpanderPlugin | Populates the attribute form with existing visibility data. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui |
| VisibilityAttributeFormTransferMapperExpanderPlugin | Maps visibility types from the form to the attribute transfer object. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui |
| VisibilityAttributeTableFilterFormExpanderPlugin | Adds a visibility type filter to the attribute table. | | SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui |

**src/Pyz/Zed/ProductAttributeGui/ProductAttributeGuiDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Zed\ProductAttributeGui;

use Spryker\Zed\ProductAttributeGui\ProductAttributeGuiDependencyProvider as SprykerProductAttributeGuiDependencyProvider;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui\VisibilityAttributeFormDataProviderExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui\VisibilityAttributeFormExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui\VisibilityAttributeFormTransferMapperExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui\VisibilityAttributeTableCriteriaExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui\VisibilityAttributeTableConfigExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui\VisibilityAttributeTableDataExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui\VisibilityAttributeTableFilterFormExpanderPlugin;
use SprykerFeature\Zed\ProductExperienceManagement\Communication\Plugin\ProductAttributeGui\VisibilityAttributeTableHeaderExpanderPlugin;

class ProductAttributeGuiDependencyProvider extends SprykerProductAttributeGuiDependencyProvider
{
    /**
     * @return array&lt;\Spryker\Zed\ProductAttributeGuiExtension\Dependency\Plugin\AttributeTableConfigExpanderPluginInterface&gt;
     */
    protected function getAttributeTableConfigExpanderPlugins(): array
    {
        return [
            new VisibilityAttributeTableConfigExpanderPlugin(),
        ];
    }

    /**
     * @return array&lt;\Spryker\Zed\ProductAttributeGuiExtension\Dependency\Plugin\AttributeTableHeaderExpanderPluginInterface&gt;
     */
    protected function getAttributeTableHeaderExpanderPlugins(): array
    {
        return [
            new VisibilityAttributeTableHeaderExpanderPlugin(),
        ];
    }

    /**
     * @return array&lt;\Spryker\Zed\ProductAttributeGuiExtension\Dependency\Plugin\AttributeTableDataExpanderPluginInterface&gt;
     */
    protected function getAttributeTableDataExpanderPlugins(): array
    {
        return [
            new VisibilityAttributeTableDataExpanderPlugin(),
        ];
    }

    /**
     * @return array&lt;\Spryker\Zed\ProductAttributeGuiExtension\Dependency\Plugin\AttributeTableCriteriaExpanderPluginInterface&gt;
     */
    protected function getAttributeTableCriteriaExpanderPlugins(): array
    {
        return [
            new VisibilityAttributeTableCriteriaExpanderPlugin(),
        ];
    }

    /**
     * @return array&lt;\Spryker\Zed\ProductAttributeGuiExtension\Dependency\Plugin\AttributeFormExpanderPluginInterface&gt;
     */
    protected function getAttributeFormExpanderPlugins(): array
    {
        return [
            new VisibilityAttributeFormExpanderPlugin(),
        ];
    }

    /**
     * @return array&lt;\Spryker\Zed\ProductAttributeGuiExtension\Dependency\Plugin\AttributeFormDataProviderExpanderPluginInterface&gt;
     */
    protected function getAttributeFormDataProviderExpanderPlugins(): array
    {
        return [
            new VisibilityAttributeFormDataProviderExpanderPlugin(),
        ];
    }

    /**
     * @return array&lt;\Spryker\Zed\ProductAttributeGuiExtension\Dependency\Plugin\AttributeFormTransferMapperExpanderPluginInterface&gt;
     */
    protected function getAttributeFormTransferMapperExpanderPlugins(): array
    {
        return [
            new VisibilityAttributeFormTransferMapperExpanderPlugin(),
        ];
    }

    /**
     * @return array&lt;\Spryker\Zed\ProductAttributeGuiExtension\Dependency\Plugin\AttributeTableFilterFormExpanderPluginInterface&gt;
     */
    protected function getAttributeTableFilterFormExpanderPlugins(): array
    {
        return [
            new VisibilityAttributeTableFilterFormExpanderPlugin(),
        ];
    }
}
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure that the attribute management UI in the Back Office includes the visibility features:

1. In the Back Office, go to **Catalog &gt; Attributes**.
2. Verify that the attribute table has a **Display At** column with visibility badges.
3. Verify that you can filter the table by visibility type using the filter dropdown.
4. Click **Edit** next to an attribute.
5. Verify that the attribute form includes a **Display At** field where you can select one or more visibility types.

{% endinfo_block %}

## 4) Set up widgets

Register the following global widgets:

| WIDGET | DESCRIPTION | NAMESPACE |
| --- | --- | --- |
| ProductAttributeVisibilityPdpWidget | Displays product attributes configured for PDP visibility with schema.org structured data. | SprykerFeature\Yves\ProductExperienceManagement\Widget |
| ProductAttributeVisibilityPlpWidget | Displays product attributes configured for PLP visibility as badges. | SprykerFeature\Yves\ProductExperienceManagement\Widget |
| ProductAttributeVisibilityCartWidget | Displays product attributes configured for Cart visibility as badges. | SprykerFeature\Yves\ProductExperienceManagement\Widget |

**src/Pyz/Yves/ShopApplication/ShopApplicationDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Yves\ShopApplication;

use SprykerFeature\Yves\ProductExperienceManagement\Widget\ProductAttributeVisibilityCartWidget;
use SprykerFeature\Yves\ProductExperienceManagement\Widget\ProductAttributeVisibilityPdpWidget;
use SprykerFeature\Yves\ProductExperienceManagement\Widget\ProductAttributeVisibilityPlpWidget;
use SprykerShop\Yves\ShopApplication\ShopApplicationDependencyProvider as SprykerShopApplicationDependencyProvider;

class ShopApplicationDependencyProvider extends SprykerShopApplicationDependencyProvider
{
    /**
     * @return list&lt;string&gt;
     */
    protected function getGlobalWidgets(): array
    {
        return [
            ProductAttributeVisibilityPdpWidget::class,
            ProductAttributeVisibilityPlpWidget::class,
            ProductAttributeVisibilityCartWidget::class,
        ];
    }
}
```

## 5) Set up Yves templates

If you have overridden the default Twig templates at the project level, add the following widget calls to display product attributes on the Storefront.

### Product Detail Page (PDP)

**src/Pyz/Yves/ProductDetailPage/Theme/default/components/molecules/product-detail/product-detail.twig**

{% raw %}

```twig
{% widget &apos;ProductAttributeVisibilityPdpWidget&apos; args [data.product.idProductAbstract, data.product.idProductConcrete | default(null),] only %}
{% nowidget %}
{% endwidget %}
```

{% endraw %}

### Product Listing Page (PLP)

**src/Pyz/Yves/ProductWidget/Theme/default/components/molecules/catalog-product/catalog-product.twig**

{% raw %}

```twig
{% widget &apos;ProductAttributeVisibilityPlpWidget&apos; args [data.products, data.product.idProductAbstract] only %}
{% nowidget %}
{% endwidget %}
```

{% endraw %}

If you have overridden `Yves/CatalogPage/Theme/default/templates/page-layout-catalog/page-layout-catalog.twig` at the project level, update the `CatalogPageProductWidget` call to pass `data.products` as an additional argument:

**src/Pyz/Yves/CatalogPage/Theme/default/templates/page-layout-catalog/page-layout-catalog.twig**

{% raw %}

```twig
{% widget &apos;CatalogPageProductWidget&apos; args [product, data.viewMode, data.products] with {
```

{% endraw %}

If you have overridden `Yves/ShopUi/Theme/default/components/molecules/product-item/product-item.twig` or `Yves/ShopUi/Theme/default/components/molecules/product-item-list/product-item-list.twig` at the project level, add the following block to each template in the location where the widget should be rendered:

**src/Pyz/Yves/ShopUi/Theme/default/components/molecules/product-item/product-item.twig**
**src/Pyz/Yves/ShopUi/Theme/default/components/molecules/product-item-list/product-item-list.twig**

{% raw %}

```twig
{% block productAttributeVisibility %}{% endblock %}
```

{% endraw %}

### Cart

**src/Pyz/Yves/CartPage/Theme/default/components/molecules/product-cart-item/product-cart-item.twig**

{% raw %}

```twig
{% widget &apos;ProductAttributeVisibilityCartWidget&apos; args [data.cart is iterable ? null : data.cart, data.product.idProductAbstract, data.product.idProductConcrete] only %}
{% nowidget %}
{% endwidget %}
```

{% endraw %}

{% info_block warningBox &quot;Verification&quot; %}

Make sure the product attributes are displayed on the Storefront based on their visibility configuration:

1. In the Back Office, configure an attribute with **PDP** visibility.
2. On the Storefront, open the product detail page and verify the attribute is displayed.
3. Configure an attribute with **PLP** visibility and verify it appears as a badge on the product listing page.
4. Configure an attribute with **Cart** visibility and add the product to the cart. Verify the attribute badge is displayed in the cart.

{% endinfo_block %}

## 6) Set up data import

### Add facade dependencies

Register the required facade dependencies in the data import module.

**src/Pyz/Zed/DataImport/DataImportDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Zed\DataImport;

use Spryker\Zed\DataImport\DataImportDependencyProvider as SprykerDataImportDependencyProvider;
use Spryker\Zed\Kernel\Container;

class DataImportDependencyProvider extends SprykerDataImportDependencyProvider
{
    /**
     * @var string
     */
    public const FACADE_PRODUCT_EXPERIENCE_MANAGEMENT = &apos;FACADE_PRODUCT_EXPERIENCE_MANAGEMENT&apos;;

    public function provideBusinessLayerDependencies(Container $container): Container
    {
        $container = parent::provideBusinessLayerDependencies($container);
        $container = $this-&gt;addProductExperienceManagementFacade($container);

        return $container;
    }

    protected function addProductExperienceManagementFacade(Container $container): Container
    {
        $container-&gt;set(static::FACADE_PRODUCT_EXPERIENCE_MANAGEMENT, function (Container $container) {
            return $container-&gt;getLocator()-&gt;productExperienceManagement()-&gt;facade();
        });

        return $container;
    }
}
```

### Update the product management attribute writer

Extend `ProductManagementAttributeWriter` to handle the `visibility` column during import. The writer saves the visibility value to the `spy_product_management_attribute` table, triggers a publish event, and validates visibility types against the allowed values.

**src/Pyz/Zed/DataImport/Business/Model/ProductManagementAttribute/ProductManagementAttributeWriter.php**

```php
&lt;?php

namespace Pyz\Zed\DataImport\Business\Model\ProductManagementAttribute;

use Spryker\Zed\DataImport\Business\Exception\DataImportException;
use Spryker\Zed\DataImport\Business\Model\DataImportStep\PublishAwareStep;
use Spryker\Zed\DataImport\Business\Model\DataSet\DataSetInterface;
use SprykerFeature\Shared\ProductExperienceManagement\ProductExperienceManagementConfig;
use SprykerFeature\Zed\ProductExperienceManagement\Business\ProductExperienceManagementFacadeInterface;

class ProductManagementAttributeWriter extends PublishAwareStep implements DataImportStepInterface
{
    protected const string KEY_VISIBILITY = &apos;visibility&apos;;

    public function __construct(
        protected readonly ProductExperienceManagementFacadeInterface $productExperienceManagementFacade,
    ) {
    }

    public function execute(DataSetInterface $dataSet): void
    {
        // ... existing logic for finding or creating entity ...

        $visibility = (string)$dataSet[static::KEY_VISIBILITY] ?? &apos;&apos;;

        if ($visibility !== &apos;&apos;) {
            $visibility = $this-&gt;normalizeVisibility($visibility, $dataSet[&apos;key&apos;]);
        }

        $productManagementAttributeEntity
            -&gt;setAllowInput($dataSet[&apos;allow_input&apos;])
            -&gt;setInputType($dataSet[&apos;input_type&apos;])
            -&gt;setVisibility($visibility);

        $productManagementAttributeEntity-&gt;save();

        $this-&gt;addPublishEvents(
            ProductExperienceManagementConfig::PRODUCT_ATTRIBUTE_PUBLISH,
            $productManagementAttributeEntity-&gt;getIdProductManagementAttribute(),
        );

        // ... existing logic for attribute values ...
    }

    protected function normalizeVisibility(string $visibility, string $attributeKey): string
    {
        $visibilityTypes = array_map(&apos;trim&apos;, explode(&apos;,&apos;, $visibility));
        $allowedVisibilityTypes = $this-&gt;productExperienceManagementFacade-&gt;getAvailableVisibilityTypes();
        $allowedVisibilityTypesMap = array_combine(
            array_map(&apos;strtolower&apos;, $allowedVisibilityTypes),
            $allowedVisibilityTypes,
        );

        $normalized = [];

        foreach ($visibilityTypes as $visibilityType) {
            $canonical = $allowedVisibilityTypesMap[strtolower($visibilityType)] ?? null;
            if ($canonical === null) {
                throw new DataImportException(
                    sprintf(
                        &apos;Invalid visibility type &quot;%s&quot; for attribute &quot;%s&quot;. Allowed: %s (or empty).&apos;,
                        $visibilityType,
                        $attributeKey,
                        implode(&apos;, &apos;, $allowedVisibilityTypes),
                    ),
                );
            }

            $normalized[] = $canonical;
        }

        return implode(&apos;,&apos;, $normalized);
    }
}
```

Wire the facade into the writer via the business factory.

**src/Pyz/Zed/DataImport/Business/DataImportBusinessFactory.php**

```php
&lt;?php

namespace Pyz\Zed\DataImport\Business;

use Pyz\Zed\DataImport\Business\Model\ProductManagementAttribute\ProductManagementAttributeWriter;
use Pyz\Zed\DataImport\DataImportDependencyProvider;
use Spryker\Zed\DataImport\Business\DataImportBusinessFactory as SprykerDataImportBusinessFactory;
use SprykerFeature\Zed\ProductExperienceManagement\Business\ProductExperienceManagementFacadeInterface;

class DataImportBusinessFactory extends SprykerDataImportBusinessFactory
{
    // In createProductManagementAttributeImporter(), replace:
    //     -&gt;addStep(new ProductManagementAttributeWriter());
    // with:
    //     -&gt;addStep(new ProductManagementAttributeWriter(
    //         $this-&gt;getProductExperienceManagementFacade(),
    //     ));

    protected function getProductExperienceManagementFacade(): ProductExperienceManagementFacadeInterface
    {
        return $this-&gt;getProvidedDependency(DataImportDependencyProvider::FACADE_PRODUCT_EXPERIENCE_MANAGEMENT);
    }
}
```

### Prepare and import data

1. Add the `visibility` column to the existing `product_management_attribute.csv` file.

   File: **data/import/common/common/product_management_attribute.csv**

```csv
key,input_type,allow_input,is_multiple,values,key_translation.en_US,key_translation.de_DE,value_translations.en_US,value_translations.de_DE,visibility
storage_capacity,text,no,no,&quot;16 GB, 32 GB, 64 GB, 128 GB&quot;,Storage Capacity,Speichergröße,,,PDP
color,text,no,yes,&quot;white, black, grey&quot;,Color,Farbe,&quot;white, black, grey&quot;,&quot;weiß, schwarz, grau&quot;,&quot;PDP,PLP,Cart&quot;
brand,text,yes,no,,Brand,Marke,,,PDP
internal_sku,text,yes,no,,Internal SKU,Interne SKU,,,,
```

| COLUMN | REQUIRED | DATA TYPE | DATA EXAMPLE | DATA EXPLANATION |
| --- | --- | --- | --- | --- |
| key | ✓ | string | color | Unique attribute key. |
| input_type | ✓ | string | text | Input type for the attribute. |
| allow_input | ✓ | string | no | Whether custom input is allowed. |
| is_multiple | ✓ | string | no | Whether multiple values are supported. |
| values | | string | &quot;white, black, grey&quot; | Predefined attribute values. |
| visibility | | string | &quot;PDP,PLP,Cart&quot; | Comma-separated list of visibility types. Valid values: `PDP`, `PLP`, `Cart`. Leave empty for internal-only attributes. |

2. Import data:

```bash
console data:import product-management-attribute
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure that the product attribute visibility data is imported correctly:

1. In the Back Office, go to **Catalog &gt; Attributes**.
2. Verify that each attribute displays the correct visibility types in the **Display At** column.
3. Check that the `spy_product_management_attribute` table contains the correct `visibility` values.

{% endinfo_block %}
</description>
            <pubDate>Mon, 04 May 2026 15:00:02 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/product-information-management/latest/base-shop/install-and-upgrade/install-features/install-the-product-attribute-visibility-feature.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/product-information-management/latest/base-shop/install-and-upgrade/install-features/install-the-product-attribute-visibility-feature.html</guid>
            
            
        </item>
        
        <item>
            <title>Release notes 202604.0</title>
            <description>Spryker Cloud Commerce OS is an end-to-end solution for digital commerce. This document contains a business-level description of new features and improvements.

For information about installing Spryker, see [Getting started guide](/docs/dg/dev/development-getting-started-guide).

## B2B Business-Ready Commerce Experiences

### Back Office Configuration Framework is now Generally Available {% include badge.html type=&quot;feature&quot; %}

Spryker has made the Back Office Configuration Framework generally available, delivering key enterprise‑readiness improvements. The release enhances governance, discoverability, and usability for managing business‑relevant configuration directly in the Back Office. Configuration changes are now easier to understand, control, and audit.

{% include carousel.html
images=&quot;
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/backoffice_framework.png||&quot;
%}

**Key capabilities:**
- Audit logging for configuration changes
- Improved search and discoverability of configuration options
- UX enhancements for a more reliable configuration experience
- CLI-based import support for faster setup and operational workflows
- Clear visibility into conflicts between code-based and Back Office configuration

**Business benefits:**
- Reduces time-to-change by enabling operations teams to adjust configuration without developer involvement, backed by a full audit trail.
- Minimizes the risk of costly production disruptions through better validation and conflict visibility before changes go live.
- Supports broader enterprise adoption with stronger governance and operability.

**Documentation:**
- [Back Office Configuration Framework](/docs/pbc/all/back-office/latest/base-shop/backoffice-configuration-framework.html)
- [Developer Guide Configuration Management](/docs/dg/dev/backend-development/configuration-management)
- [Install the Back Office Configuration Framework feature](/docs/dg/dev/integrate-and-configure/integrate-confguration-feature.html)

### Basic Shop Theming {% include badge.html type=&quot;feature&quot; %}

Business users can now manage core branding settings directly in the Back Office without code changes or deployments. This provides a standardized way to apply basic theming across Storefront, the Back Office, and Merchant Portal.

{% include carousel.html
images=&quot;
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/theming_1.png||::
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/theming_2.png||&quot;
%}

**Key capabilities:**
- Supports theme management with global and store-specific scope.
- Lets users upload and manage logos for Storefront, the Back Office, and Merchant Portal.
- Provides configuration for core brand colors, button styles and text colors.
- Uses a standardized Back Office configuration experience for theme administration.

**Business benefits:**
- Speeds up demo preparation, POCs, and early customer activation through instant, self-service branding configuration.
- Shop operators can now apply and adjust their brand CI across all Spryker touchpoints at any time directly in the Back Office, without developer involvement or redeployment.

**Documentation:**
- [Feature Overview](/docs/pbc/all/cart-and-checkout/latest/base-shop/feature-overviews/purchasing-control-feature-overview.html)
- [Installation Guide](/docs/pbc/all/cart-and-checkout/latest/base-shop/install-and-upgrade/install-features/install-the-purchasing-control-feature.html)

### Budget &amp; Cost Centers {% include badge.html type=&quot;feature,early-access&quot; %}

We introduced an Early Access version of budgets and cost centers to support policy-driven purchasing in B2B procurement. The release covers core budget enforcement and its integration with approval workflows.

**Key capabilities:**
- Lets companies create and manage cost centers and assign buyers to them.
- Supports budget creation with configurable enforcement rules such as block, warn, or require approval.
- Adds cost center selection and budget validation during checkout.
- Integrates budget-triggered approvals with Spryker&apos;s existing Approval Process.
- Tracks budget consumption and restoration as orders progress.

**Business benefits:**
- Improves financial control and purchasing compliance.
- Reduces overspending risk with enforceable budget rules.
- Aligns procurement workflows with departmental or project-based spending structures.
- Provides an early demoable foundation for customer and partner conversations.

**Documentation:**
- [Purchasing Control Feature Overview](/docs/pbc/all/cart-and-checkout/latest/base-shop/feature-overviews/purchasing-control-feature-overview)
- [Install Purchasing Control Feature Overview](/docs/pbc/all/cart-and-checkout/latest/base-shop/install-and-upgrade/install-features/install-the-purchasing-control-feature)

### Back Office Product Import &amp; Export {% include badge.html type=&quot;feature,early-access&quot; %}

Spryker now offers product import and export via the Back Office, reducing reliance on developer‑driven CLI tooling. Business users can prepare and update catalogs faster during onboarding, launches, and routine maintenance. This improves operational speed and gives teams more control over their product data processes.

{% include carousel.html
images=&quot;
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/bo_import_export_1.png||::
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/bo_import_export_2.png||::
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/bo_import_export_3.png||&quot;
%}

**Key capabilities:**
- Import and export product data directly from the Back Office
- Single‑file product import, replacing multiple CLI‑required files
- CSV‑based jobs with reusable job/run concepts and clear validation feedback

**Business benefits:**
- Significantly simplifies adding products to the catalog, replacing multi‑file CLI imports with a single, business‑friendly file
- Accelerates catalog preparation for new launches and environment migrations
- Empowers business users with self‑service error resolution, minimizing developer involvement

**Documentation:**
- [Product Experience Management](/docs/pbc/all/product-experience-management/latest/product-experience-management.html)
- [Install the Product Experience Management feature](/docs/pbc/all/product-experience-management/latest/install-the-product-experience-management-feature.html)

### Product attribute display types {% include badge.html type=&quot;feature&quot; %}

You can now control where product attributes are visible without project-specific customization. This helps keep internal operational data hidden while displaying only relevant information to buyers.

**Key capabilities:**
- Adds visibility types for product attributes.
- Supports internal-only attributes as well as attributes shown on PDP, PLP, and cart-related experiences.
- Provides native configuration for attribute visibility management.

**Business benefits:**
- Shop operators can now control which attributes are displayed where across the storefront, making it easier to surface the right product information at the right place to support buyer decision-making and product discovery.
- Internal attributes can be managed separately to support operational or process-related needs without ever being exposed to buyers.

**Documentation:**
- [Product Attribute Display Types](/docs/pbc/all/product-information-management/latest/base-shop/feature-overviews/product-feature-overview/product-attribute-visibility-overview)
- [Install Product Attribute Visibility Feature](/docs/pbc/all/product-information-management/latest/base-shop/install-and-upgrade/install-features/install-the-product-attribute-visibility-feature)

### Spryker Storefront Design System Foundation {% include badge.html type=&quot;feature&quot; %}

Building storefronts without a common foundation meant repeated work, slower delivery, and experiences that looked and felt different every time. This release introduces a unified design system with shared foundations and reusable components, so teams work from common building blocks. The result is faster implementation, easier adoption, and the ability to scale storefront delivery without scaling complexity.

**Key capabilities:**
- Defines the design system foundation with shared tokens and naming conventions.
- Introduces token-driven implementation patterns for new storefront components.
- Adds composite component patterns built from core UI elements.
- Covers common structures such as cards, buttons, input fields, headers, search and more.

**Business benefits:**
- Improves consistency across storefront experiences.
- Reduces duplicate design and frontend implementation effort.
- Accelerates feature delivery with reusable UI patterns.
- Creates a stronger foundation for future storefront evolution.

**Documentation:**
- [How to use design system tokens](/docs/dg/dev/frontend-development/latest/design-tokens#how-it-works)

### Back Office support for merchant product ownership {% include badge.html type=&quot;improvement&quot; %}

Marketplace operators can now manage merchant ownership of products directly in the Back Office, without relying on the Merchant Portal. This makes it easier to maintain accurate product data in centrally managed or hybrid marketplace models. The result is smoother operations and clearer accountability across the catalog.

**Key capabilities:**
- Assign or update merchant ownership for any product directly in Back Office workflows.
- See merchant ownership instantly within product management views.
- Maintain merchant‑related product data as part of your standard PIM processes.

**Business benefits:**
- Strengthens support for centrally managed catalogs and hybrid marketplace models, giving operators more flexibility in how they run their marketplace.
- Improves transparency and control, making ownership clear, consistent, and auditable.
- Reduces reliance on workarounds and custom tooling, lowering operational overhead.
- Supports more flexible marketplace operations, enabling teams to scale product management with confidence.

**Documentation:**
- [Marketplace Create Abstract Products](/docs/pbc/all/product-information-management/latest/marketplace/manage-in-the-back-office/products/abstract-products/create-abstract-products#defining-general-settings)

### Back Office Frontend Modernisation {% include badge.html type=&quot;improvement&quot; %}

We delivered the first phase of the Back Office theme modernisation to improve clarity, consistency, and responsiveness. This update creates a more usable and scalable visual foundation without changing the overall information architecture.

**Key capabilities:**
- Improves visual hierarchy and component consistency across the Back Office.
- Reduces UX debt introduced by legacy Inspinia defaults.
- Enhances spacing, density, emphasis, and table presentation.
- Provides a more stable foundation for future Back Office UX improvements.

**Business benefits:**
- Improves daily usability for Back Office users.
- Makes the Back Office more credible and demo-ready.
- Reduces the need for one-off CSS customizations.
- Establishes a better base for future product evolution.

### Streamlined Login and Session Recovery Experience {% include badge.html type=&quot;improvement&quot; %}

Logging in should feel like picking up where you left off, not starting over. With this release, users across the Back Office, Storefront, and Marketplace are presented with a meaningful dashboard featuring quick actions for common tasks, including viewing orders, adding products, and checking returns. After a session timeout, users are redirected back to the page they were on so they do not lose track of what they were doing.

**Key capabilities:**
- Redirects Back Office users to the dashboard instead of a blank technical page after login.
- Adds action-oriented quick actions to the Back Office dashboard for common tasks such as viewing orders, adding products, opening the catalog, and checking returns.
- Restores the last visited page after session timeout across the Back Office, Storefront, and Marketplace.
- Reopens create and edit pages after re-login, while unsaved data is not preserved.

**Business benefits:**
- Reduces onboarding friction for new users.
- Helps operational users continue workflows faster after session expiration.
- Improves usability and perceived product maturity across core daily journeys.
- Makes demos and first-touch product experiences more intuitive.

## Connected, and AI-Enabled Platform

### Spryker Now Ships with AI Foundation and Smart Product Enrichment {% include badge.html type=&quot;improvement,early-access&quot; %}

Spryker now includes the AI Foundation and Smart PIM out of the box, allowing merchants to adopt AI‑assisted catalog enrichment with minimal setup. Product content can be improved, translated, and enriched directly in the Back Office using AI, reducing manual work and improving content quality. Customers only need to connect their preferred AI provider to start benefiting from AI‑powered product enhancements, with governance automatically handled through AI Foundation.

**Key capabilities**
- Enhances and translates product names and descriptions using AI
- Generates alt‑text for product images and suggests suitable product categories
- Delivered by default in Spryker, requiring only AI provider configuration

**Business benefits**
- Reduces manual effort in creating and refining product content across the catalog
- Makes AI adoption easier by providing a pre‑configured integration layer with built‑in governance and provider flexibility
- Speeds up catalog enrichment and localization for merchants operating across multiple markets

**Documentation**
- [AI Foundation Overview](/docs/dg/dev/ai/ai-foundation/ai-foundation-module)
- [Smart PIM](/docs/pbc/all/ai-commerce/latest/smart-pim)

### Smart Back Office Assistant {% include badge.html type=&quot;feature,early-access&quot; %}

Spryker introduces the Smart Back Office Assistant, enabling operators to perform Back Office tasks through natural language instead of relying solely on manual navigation. Operators can get guidance on where to find features, ask operational and order‑related questions, and create discounts directly through chat. This makes Back Office work faster, more intuitive, and easier for all user types.

{% include carousel.html
images=&quot;
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/bo_ai_assistant.png||&quot;
%}

**Key capabilities**
- Provides navigation and operational guidance to help users quickly find functions and understand Back Office workflows
- Answers order‑related questions, including order status and operational details
- Assists to complete forms, for example, by enabling discount creation directly through chat.

**Business benefits**
- Reduces time spent searching for pages and completing repetitive tasks
- Improves usability for operators who are less familiar with Back Office structure or workflows
- Helps prevent errors by guiding operators through correctly structured inputs and actions

**Documentation**
- [Back Office Assistant](/docs/dg/dev/ai/ai-commerce/ai-commerce-overview.html)
- [Install Back Office Assistant](/docs/dg/dev/ai/ai-commerce/backoffice-assistant/install-backoffice-assistant.html)

### AI Foundation Visibility &amp; Governance Enhancements {% include badge.html type=&quot;feature,early-access&quot; %}

Spryker introduces comprehensive visibility into AI activity through new Back Office views for both AI interactions and AI workflow execution. Teams can now inspect prompts, responses, metadata, and workflow states in a single place, improving transparency and control over AI‑driven processes. These enhancements strengthen governance, streamline troubleshooting, and make AI operations easier to understand and monitor.

{% include carousel.html
images=&quot;
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/bo_ai_auditlogs_1.png||::
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/bo_ai_auditlogs_2.png||&quot;
%}

**Key capabilities:**
- Back Office audit logs for reviewing prompts, responses, metadata, and model details
- Workflow execution views with list, detail, state history, and visualized transitions
- Filtering, sorting, and inline inspection tools for efficient debugging and analysis

**Business benefits:**
- Improves governance and traceability across all AI‑powered processes
- Simplifies troubleshooting by making AI interactions and workflow states fully transparent
- Gives operators greater control over AI‑driven actions with clear visibility into execution paths

**Documentation:**
- [AI Foundation Audit Logs](/docs/dg/dev/ai/ai-foundation/ai-foundation-audit-logs.html)
- [AI Foundation Workflows](/docs/dg/dev/ai/ai-foundation/ai-foundation-workflow-state-machine)

### Smart Visual Product Search &amp; Ordering {% include badge.html type=&quot;improvement,early-access&quot; %}

Spryker now enables buyers to identify products and start orders simply by uploading or capturing an image. Whether it&apos;s a technical part, a field-site photo, or a handwritten note, the system can recognize products and quantities and help buyers move directly from identification to ordering. The entire capability now runs on the Spryker AI Foundation, offering provider flexibility, improved reliability, and easier long‑term adoption.

**Key capabilities**
- Helps buyers identify relevant or visually similar products by uploading or capturing an image
- Prefills the quick order form with products and quantities extracted from photos, screenshots, or handwritten notes
- Uses Spryker AI Foundation for multi‑provider support (OpenAI, Azure, Bedrock) and centralized AI governance

**Business benefits**
- Speeds up product identification and ordering, especially for technical and spare‑parts workflows
- Reduces manual entry and ordering errors by interpreting product information directly from images
- Supports mobile and field‑based buying scenarios where buyers capture photos instead of searching by name or SKU

**Documentation**
- [Search by Image](/docs/pbc/all/ai-commerce/latest/search-by-image)
- [Visual Add to Cart](/docs/pbc/all/ai-commerce/latest/visual-add-to-cart)
- [Install Search by Image](/docs/dg/dev/ai/ai-commerce/search-by-image/install-search-by-image)
- [Install Visual Add to Cart](/docs/dg/dev/ai/ai-commerce/visual-add-to-cart/install-visual-add-to-cart)

### AI Dev Tooling for Coding Agents {% include badge.html type=&quot;feature,early-access&quot; %}

Spryker now provides ready-to-use new AI Dev tooling to help development teams work more effectively with coding agents in Spryker projects. The update provides ready-to-use agent instruction files and reusable Spryker-specific skill examples.

**Key capabilities:**
- Generates a project‑ready agent configuration file (AGENTS.md)
- Generates a set of rules for AI agent based on Spryker coding conventions and architectural guidelines
- Provides reusable skill examples covering testing, data import, schema conventions, validation, and frontend development
- Includes a setup command that generates agent configuration file, rules and skills for supported coding agents

**Business benefits:**
- Speeds up onboarding for developers who are new to Spryker by giving AI coding agents the right context from day one
- Improves code quality and consistency through pre‑written, Spryker‑aligned development rules
- Helps teams deliver features faster by reducing back‑and‑forth with AI tools and minimizing incorrect code generation

**Documentation:**
- [AI Dev SDK](/docs/dg/dev/ai/ai-dev/ai-dev-overview)

### API Platform is now Generally Available {% include badge.html type=&quot;feature&quot; %}

Spryker made API Platform generally available as the foundation for modern API development and migration. Existing APIs have been migrated to API Platform internally while keeping external contracts backward-compatible. This enables faster API delivery, easier extensibility, and more standardized API development.

![API Platform](https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202512/api-platform-2.6-api.png)

**Key capabilities:**
- Declarative API development using YAML schemas
- API generation with validation, pagination, serialization, and operation-specific rules
- Interactive and always up-to-date OpenAPI documentation
- Backward-compatible migration of existing APIs to API Platform infrastructure
- Cleaner separation of read and write logic through providers and processors

**Business benefits:**
- Reduces development effort for new and existing APIs
- Improves consistency and maintainability of API implementations
- Accelerates delivery of integrations and future API capabilities

**Documentation:**
- [API Platform](/docs/dg/dev/architecture/api-platform.html)
- [Migration Status of out-of-the-box API Endpoints](/docs/dg/dev/architecture/api-platform/migrate-to-api-platform-status.html)

### Algolia configuration in the Back Office {% include badge.html type=&quot;improvement&quot; %}

Spryker updated the Algolia integration settings in the Back Office to replace the legacy ACP-based configuration experience. The new page uses the Back Office Configuration Framework and provides a more consistent and user-friendly way to manage Algolia credentials. This helps reduce setup effort and simplifies validation during implementation.

**Key capabilities:**
- New configuration section in **Back Office &gt; Configuration &gt; Integrations &gt; Algolia**
- Manage Algolia credentials, including:
  - Application ID
  - Search-only API key
  - Admin API key
- Validate credentials directly via API calls
- Align Algolia setup with the current Spryker-native integration approach

**Business benefits:**
- Simplifies Algolia setup and maintenance in the Back Office
- Reduces implementation time and configuration errors
- Replaces legacy ACP-era fields with a clearer configuration experience

**Documentation:**
- [Integrate Algolia](/docs/pbc/all/search/latest/base-shop/third-party-integrations/algolia/integrate-algolia)

### Mollie PSP Integration {% include badge.html type=&quot;feature&quot; %}

Spryker introduces a new native integration with Mollie, a leading European payment service provider, enabling seamless B2B and B2C payment experiences across key European markets. The integration allows merchants to quickly enable a wide range of local and international payment methods with minimal development effort. It is delivered in collaboration with Spryker Solution Partner KPS.

**Key capabilities:**
- Native integration with Mollie
- Support for a wide range of local European and international payment methods
- Plug-and-play setup with minimal custom development

**Business benefits:**
- Faster time-to-market for European commerce use cases
- Improved conversion through localized payment experiences
- Reduced implementation complexity and maintenance overhead

**Documentation:**
- [Mollie integration](https://github.com/mollie/spryker)

### OAuth SSO readiness for Spryker applications {% include badge.html type=&quot;feature&quot; %}

Spryker introduced a standardized and reusable approach for OAuth 2.0 and OpenID Connect single sign-on across key applications. The release establishes a consistent integration pattern for identity providers such as Keycloak, Azure AD, and Okta for the Back Office, Storefront, and Merchant Portal. This makes identity integrations more predictable and reduces the need for project-specific implementations.

**Key capabilities:**
- Standardized SSO approach for:
  - the Back Office
  - Storefront
  - Merchant Portal
- Support for OAuth Authorization Code flow with PKCE
- Provider-agnostic integration based on configurable OAuth providers
- Persistent identity linking between external providers and Spryker users
- Reference implementation, templates, configuration patterns, and rollout guidance
- Backward compatibility with existing form-based login

**Business benefits:**
- Reduces time and cost for enterprise identity integrations
- Improves implementation predictability across projects
- Creates a reusable foundation for federated authentication across Spryker entry points

**Documentation:**
- [Federated Authentication via OAuth2/OIDC](/docs/pbc/all/oauth/latest/federated-authentication.html)

### Native PunchOut Gateway for cXML and OCI {% include badge.html type=&quot;feature,early-access&quot; %}

Spryker introduced native PunchOut Gateway capabilities for cXML and OCI to reduce bespoke integration work in procurement-driven B2B commerce. The release adds reusable building blocks for common PunchOut flows, including session start, shopping, cart updates, and cart return. This strengthens support for enterprise procurement environments, especially SAP-centric setups.

**Key capabilities:**
- Native compatibility for cXML and OCI PunchOut scenarios
- Support for basic PunchOut requisition and cart flows
- Standard OCI parameter handling
- OCI cart return support with line items
- Reusable message handling and implementation guidance

**Business benefits:**
- Reduces custom development effort for PunchOut implementations
- Speeds up procurement-channel enablement and time-to-revenue
- Improves repeatability and maintainability across B2B integration projects

**Documentation:**
- [PunchOut Gateway](/docs/pbc/all/punchout-gateway/punchout-gateway)

### New Stripe Integration {% include badge.html type=&quot;improvement&quot; %}

Spryker introduced a new Stripe integration that replaces the legacy ACP-based app with a more extensible Spryker-native implementation. The release also adds a dedicated configuration page in the Back Office for managing Stripe settings. This gives customers and partners more control over Stripe-based payment flows and reduces dependency on legacy integration boundaries.

**Key capabilities:**
- New installable Stripe Eco module without ACP runtime dependency
- Support for checkout payment method selection
- Support for payment initialization, authorization, capture, refund, and cancel flows
- New configuration section in **Back Office &gt; Configuration &gt; Integrations &gt; Stripe**
- Validation of Stripe keys and webhook configuration
- Storage of Stripe settings in configuration storage

**Business benefits:**
- Improves flexibility for extending and customizing Stripe payment flows
- Reduces implementation risk and legacy dependency overhead
- Lowers long-term maintenance effort and supports faster payment innovation

**Documentation:**
- [New Stripe Integration](https://github.com/spryker-eco/stripe/releases/tag/1.0.0)

### New Vertex Integration {% include badge.html type=&quot;improvement&quot; %}

Spryker introduced a new Vertex integration to replace the legacy ACP-based approach for tax calculation scenarios. The new integration is designed to provide more flexibility and reduce legacy constraints when adapting tax-related processes. This supports more maintainable and extensible tax integrations over time.

**Key capabilities:**
- New Spryker-native Vertex integration
- Reduced reliance on legacy ACP-based architecture
- Improved extensibility for tax calculation and related scenarios

**Business benefits:**
- Supports more adaptable tax integrations for changing business needs
- Reduces integration friction and project-specific patching
- Lowers total cost of ownership through improved maintainability

**Documentation:**
- [Integrate Vertex](/docs/pbc/all/tax-management/latest/base-shop/third-party-integrations/vertex/install-vertex/integrate-vertex)

### Data import performance and stability enhancements {% include badge.html type=&quot;improvement&quot; %}

We improved the data import experience and robustness for large data volumes. Data imports now provide better execution visibility through a progress bar, and memory usage has been optimized to better support very large imports, including merchant price imports with up to 1 million records.

**Key capabilities:**
- Added a progress bar for data import console commands to show execution progress.
- Reduced memory consumption in data import flows to prevent out-of-memory issues during large imports.
- Improved reliability for high-volume imports across data import entities.

**Business benefits:**
- Helps operators better monitor long-running imports.
- Reduces failures caused by memory exhaustion during large imports.
- Improves operational efficiency for bulk data onboarding.

**Documentation:**
- [Data import (memory usage)](/docs/dg/dev/guidelines/performance-guidelines/keeping-dependencies-updated.html#data-import-memory-usage)
- [Data import Progress bar](/docs/dg/dev/data-import/latest/data-import-optimization-guidelines.html#progress-bar)

### Performance and security improvements {% include badge.html type=&quot;improvement&quot; %}

We made your Spryker Commerce OS faster, more secure, and more stable.

**Key capabilities:**
- Non-buffered log streaming presents the logs immediately.
- Lower latency and response times in storefront with optimized widgets.
- Lower latency and response times in the Back Office and Merchant Portal.
- Higher stability and throughput of Publish &amp; Synchronize workers. The update introduces dynamic waiting behavior, better control over parallel job execution, and compatibility improvements for Symfony Messenger resource-aware workers.

**Documentation:**
- [Non-buffered log streaming](https://api.release.spryker.com/release-group/6411)
- [Yves widget performance best practices](/docs/dg/dev/guidelines/performance-guidelines/yves-performance-best-practice.html)
- [Split Publish &amp; Synchronize queues for performance](/docs/dg/dev/guidelines/performance-guidelines/split-queues-performance.html)
- [Merchant Portal and Back Office performance with ACL rules](/docs/dg/dev/guidelines/performance-guidelines/keeping-dependencies-updated.html#merchant-portal-and-back-office-performance-with-acl-rules)
- [Order details page performance guidance](/docs/pbc/all/order-management-system/latest/base-shop/order-management-feature-overview/order-details-page-performance-overview.html)

## Efficient and Flexible Cloud Foundation

### Spryker Monitoring Integration: logs forwarding {% include badge.html type=&quot;improvement&quot; %}

Spryker expanded cloud observability by enabling log forwarding through [SMI](/docs/ca/dev/monitoring/spryker-monitoring-integration/spryker-monitoring-integration.html) to third-party monitoring platforms of your choice. This allows teams to correlate logs with traces, create alerts based on log data, and use their preferred monitoring tooling beyond AWS CloudWatch.

{% include carousel.html
images=&quot;
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/SMI-dynatrace-logs.png||::
https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/SMI-dynatrace-traces.png||&quot;
%}

**Key capabilities:**
- Inspect logs from Spryker Platform in your monitoring tool
- Correlate logs with traces using trace and span identifiers
- Configure log verbosity to control emitted log volume

**Business benefits:**
- Improved troubleshooting through unified logs and traces
- Better alerting capabilities based on application and infrastructure log events

**Documentation:**
- [Spryker Monitoring Integration Logs](/docs/ca/dev/monitoring/spryker-monitoring-integration/opentelemetry-instrumentation#smi-logs-integration)

### Single Sign-On (SSO) for Cloud services {% include badge.html type=&quot;feature&quot; %}

Spryker introduced centralized access management for cloud services, including SSO support for customer identity providers such as Okta and OneLogin. This update reduces manual access handling, improves security, and simplifies onboarding and offboarding for users. It also includes rollout, production-readiness, and IAM cleanup measures to standardize and harden access controls.

&lt;figure class=&quot;video_container&quot;&gt;
    &lt;video width=&quot;100%&quot; height=&quot;auto&quot; controls&gt;
    &lt;source src=&quot;https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202604/2026-Cloud-Hub-SSO-Lofi.mp4&quot; type=&quot;video/mp4&quot;&gt;
  &lt;/video&gt;
&lt;/figure&gt;

**Key capabilities:**
- Connect your own identity provider for SSO access to cloud services
- Centralize user access management for services such as Jenkins, RabbitMQ, and others
- Reduce manual access management effort through self-service-oriented processes

**Business benefits:**
- Faster and more secure user onboarding and offboarding
- Reduced operational effort for access requests and changes
- TLS-encrypted communication to Jenkins and RabbitMQ over internal environment network

**Documentation:**
- [Spryker Cloud SSO Access](/docs/ca/dev/access/sso-access.html)

### Bastion security hardening {% include badge.html type=&quot;improvement&quot; %}

Spryker improved Bastion host security and maintainability by upgrading the operating system, isolating workloads from the host, and enforcing SSO and MFA for human access. This change modernizes the setup while keeping customer impact minimal and preserving SFTP access for integrations.

**Key capabilities:**
- Upgrade Bastion hosts to a current LTS operating system
- Enforce SSO and MFA for human access, deprecate direct SSH access for human users

**Business benefits:**
- Improved security posture for administrative access

### Maintenance and service updates {% include badge.html type=&quot;improvement&quot; %}

Spryker delivered maintenance updates across cloud services and application tooling to keep the platform secure, supported, and maintainable.

**Key capabilities:**
- RabbitMQ 4.2 is now supported in Docker SDK for local development environments.
- Node.js 24 introduces V8 v13.6 and npm 11, which results in noticeably faster `frontend:yves:build` and `frontend:zed:build` runs.

**Business benefits:**
- Reduced security and operational risk from outdated components

**Documentation:**
- [RabbitMQ 4.2 in Docker SDK](/docs/dg/dev/sdks/the-docker-sdk/the-docker-sdk.html)
- [Upgrade Node.js and npm](/docs/dg/dev/upgrade-and-migrate/upgrade-nodejs.html#prerequisites)

</description>
            <pubDate>Mon, 04 May 2026 14:12:48 +0000</pubDate>
            <link>https://docs.spryker.com/docs/about/all/releases/release-notes-202604.0.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/about/all/releases/release-notes-202604.0.html</guid>
            
            
        </item>
        
        <item>
            <title>Packaged Business Capabilities</title>
            <description>Packaged Business Capabilities (PBCs) are capabilities that enclose a certain functionality with the Spryker system. PBCs provide a good foundation for decision makers throughout multiple business entities.

This section is in beta because not all the PBCs are covered. Marketplace functionalities will also be added at a later stage. You are welcome to use the docs that are already here, and we will keep adding the docs for the rest of the PBCs.

## Spryker PBCs

| NAME | DESCRIPTION | BENEFITS |
| --- | --- | --- |
| [AI Foundation](/docs/pbc/all/ai-foundation/{{site.version}}/ai-foundation.html) | Provider agnostic AI layer that connects Spryker Commerce OS to leading AI providers through one common interface. | Accelerates delivery of AI features and keeps freedom to choose and change AI providers and models per use case. |
| [AI Commerce](/docs/pbc/all/ai-commerce/{{site.version}}/ai-commerce.html) | Brings AI assisted capabilities to the Spryker storefront and Backoffice to help buyers and operators complete commerce tasks faster and more consistently, reducing manual effort with human review and enterprise governance. | Speeds up key commerce workflows while improving consistency and reducing errors, enabling scalable adoption of assisted capabilities across teams and markets. |
| [Business Intelligence](/docs/pbc/all/business-intelligence/{{site.version}}/business-intelligence.html) | Analyze data to understand how your shop performs and areas for improvement. | Make informed decisions. |
| [Carrier Management](/docs/pbc/all/carrier-management/{{site.version}}/carrier-management.html) | The Spryker Cloud Commerce OS integrates with several shipping carriers and methods and lets you define their availability, price, and tax set. During the checkout process, customers have the option to select their preferred shipment method and relevant carrier. | Ensures quick and cost-effective delivery. |
| [Cart and Checkout](/docs/pbc/all/cart-and-checkout/{{site.version}}/cart-and-checkout.html) | The online shopping cart and checkout process act as a gateway for customer and order management. It lets your customers organize and manage their purchases, apply vouchers and coupon codes. Based on their roles and permissions, your B2B customers can add or remove products, share the cart, and manage their purchases. | Increases conversion rates and reduces drop-off rates. Offers additional B2B specific, permission-related functionalities. |
| [Content Management System (CMS)](/docs/pbc/all/content-management-system/{{site.version}}/content-management-system.html) | The CMS features let you customize your store, enrich it with information, stories, or other content, and make it easily findable in search engines. Several SEO features enable you to add customized meta information to all your content and create search engine-friendly URLs. | Provides compelling content and stories where your customers need it. |
| [Customer Relationship Management (CRM)](/docs/pbc/all/customer-relationship-management/{{site.version}}/customer-relationship-management.html) | The customer management tool lets B2B and B2C businesses manage customer accounts and efficiently monitor shopping habits. It provides your B2B Customers with a way to map their business hierarchies, permissions, and role management. With the creation of distinctive Business Units, the internal hierarchy can easily be mapped out, and each Unit can operate independently. The Roles and Permissions System lets your customer&apos;s buyers define the purchase and approval process. | Increases conversion rates and average order values with a compact Customer Relationship Management tool. |
| [Data Exchange](/docs/pbc/all/data-exchange/{{site.version}}/data-exchange.html) | You can import your business logic and data, including product information, customer base, categories, and more, into the Spryker Cloud Commerce OS. You can use the out-of-the-box export data functionality as a generic blueprint for any data set that you need to export. | Lets you import and export specific data points quickly and easily. |
| [Discount Management](/docs/pbc/all/discount-management/{{site.version}}/discount-management.html) | You can define several types of discounts based on a brand, the overall cart value, specific product ranges, or unique customer groups. You can also offer discount vouchers or incentivize certain products through coupon codes. | Lets you run effective promotional campaigns to boost conversion rates. |
| [Dynamic Multistore](/docs/pbc/all/dynamic-multistore/{{site.version}}/dynamic-multistore.html) | Manage stores in the Back Office | Make changes to your stores setup quickly and easily. |
| [Emails](/docs/pbc/all/emails/{{site.version}}/emails.html) | You can send automated account e-mails and confirmations or offer different types of newsletter subscriptions. | Keep in touch with your customers. |
| [Gift Cards](/docs/pbc/all/gift-cards/{{site.version}}/gift-cards.html) | Lets your customers purchase and redeem gift cards. Enabling gift card purchases can boost your brand awareness and help you reach new customers. | Lets you acquire new customers through gift card payment options. |
| [Identity Access Management (IAM)](/docs/pbc/all/identity-access-management/{{site.version}}/identity-access-management.html) | Enables the creation of new accounts for end customers and B2B customers. It also allows users to define password settings and utilize multi-login blockers for security purposes. Moreover, a third-party access management function is integrated. | Allows for quick and easy authorization and authentication of customers |
| [Merchant Management](/docs/pbc/all/merchant-management/{{site.version}}/merchant-management.html) | For efficient Merchant Management, two parts are important. One, the overview and management on the Operator side, like approvals, edits, etc. And two, the self-service management of the Merchants, where they can take care of their daily business, like order or product management. | Gives you an overview of all your Merchants&apos; activities. |
| Miscellaneous | This category holds the documents that are not related to any PBC.  |  |
| [Offer Management](/docs/pbc/all/offer-management/{{site.version}}/offer-management.html) | Lets your Merchants create Offers on existing products in your Marketplace. By doing so, duplicates in the product catalog can be avoided and the management of Merchants, Products, and Offers becomes much more convenient. | Saves time because of a good overview of Merchant&apos;s Offers. |
| [Order Management System (OMS)](/docs/pbc/all/order-management-system/{{site.version}}/order-management-system.html) | Helps you keep track of your order processing from your B2B, B2C, or Marketplace, and ensure quick fulfillment. You can manage incoming orders in the Back Office, view and edit orders, track their progress, or contact customers who make open orders directly. With the compact Order Management features, you can keep your order processing running smoothly. | Lets you pProcess orders smoothly to fulfill them quickly. |
| [Payment Service Provider (PSP)](/docs/pbc/all/payment-service-provider/{{site.version}}/payment-service-provider.html) | Provides integration of payment methods. You can integrate multiple payment gateways, define their availability, and customize how they appear on your site. | Lets you provide an excellent shopping experience and integrate your customers&apos; preferred payment methods. |
| [Price Management](/docs/pbc/all/price-management/{{site.version}}/price-management.html) | The Spryker Cloud Commerce OS supports multiple currencies and automatically detects the payment currency based on a customer&apos;s preference. You can manage gross and net prices per product and per country. You can also offer volume discounts to encourage customers to purchase products in larger quantities. | Saves you time by letting you implement your pricing strategy in one place and catering it to your business needs. |
| [Product Information Management (PIM)](/docs/pbc/all/product-information-management/{{site.version}}/product-information-management.html) | Encompasses all functionality that is needed to set up your product catalog. With PIM, you can create and extend the product catalog to match your business needs. | Helps you expand your business by organizing your products in a fast and efficient way. |
| [Product Relationship Management](/docs/pbc/all/product-relationship-management/{{site.version}}/product-relationship-management.html) | Helps you enhance your shop with cross- and up-selling capabilities to increase sales. | Increases average order values with product relations. |
| [Ratings and Reviews](/docs/pbc/all/ratings-reviews/{{site.version}}/ratings-and-reviews.html) | Lets you incorporate user reviews and ratings. You can receive and moderate feedback in the Back Office. The Ratings and Reviews feature also comes with the functionality to add text-free reviews and star ratings. | Inspires trust among customers with ratings and reviews. |
| [Request for Quote (RFQ)](/docs/pbc/all/request-for-quote/{{site.version}}/request-for-quote.html) | Your customers can request a quote for products and services that you sell. The Request for Quote feature supports all functionalities of the price engine and product capabilities, such as Volume Prices, Customer Specific Prices, Measuring and Packaging units, Shipping costs, Product Options, etc. | Enhances customer loyalty and increase conversion rates. |
| [Return Management](/docs/pbc/all/return-management/{{site.version}}/marketplace/marketplace-return-management-feature-overview.html) | Lets you establish a return policy and execute returns. | Increase customer satisfaction and loyalty. |
| [Search](/docs/pbc/all/search/{{site.version}}/base-shop/search-feature-overview/search-feature-overview.html) | The out-of-the-box Elasticsearch technology lets you include full-text search, auto-suggestions, and auto-completion. You can set individual search preferences for multiple stores and categorize your products by adding dynamic filters and facets to help your customers further refine the search results. You can also add more advanced filters that use the product&apos;s metadata or promote a brand&apos;s top-sellers or highly rated products. | Helps you increase conversion rates by providing an excellent Search and Filter experience. |
| [Service Points Management](/docs/pbc/all/service-point-management/{{site.version}}/service-point-management.html) | Set up offline service points where customers can interact with your business. | Creates touch points to connect a shop with offline locations. |
| [Shopping List and Wishlist](/docs/pbc/all/shopping-list-and-wishlist/{{site.version}}/shopping-list-and-wishlist.html) | Your B2B customers can save the products they wish to purchase, in shopping lists. Different roles and permission systems ensure smooth sharing and contribution management amongst company users. This PBC encompasses additional features like printing, barcode generation, and direct-to-cart. Enabling your B2C customers to track and save the products they wish to purchase through a wish list function effectively reduces cart abandonment, boosts your sales, and allows you to keep track of which products are of interest to your customers. | Lets you increase conversion rates and loyalty by offering rich Shopping and B2B Wish Lists. |
| [Tax Management](/docs/pbc/all/tax-management/{{site.version}}/tax-management.html) | Lets you adhere to respective tax regulations in the countries you sell by configuring and managing tax rates for products, shipments, and additional services. You can define tax rates for different countries and apply integrations to manage US taxes. | Lets you comply with fiscal regulations. |
| [User Management](/docs/pbc/all/user-management/{{site.version}}/user-management.html) | Lets the Back Office users manage user access, set rights, and onboard customers. | Ensures high security and compliance through managed user flows. |
| [Warehouse Management System (WMS)](/docs/pbc/all/warehouse-management-system/{{site.version}}/warehouse-management-system.html) | Lets you keep an overview of your stock levels in the Back Office to determine accurate availabilities on your store&apos;s website. Any open orders or reserved items are taken into consideration when stock availabilities are displayed. | Helps you save your time by keeping an eye on your stock levels. |

&lt;!--
| Digital Asset Management (DAM) | The DAM system provides impactful visuals while simultaneously maintaining fast response times, thus helping you reduce your bounce rate effectively and create an enhanced shopping experience. With the DAM, you can add images and videos to any of your pages. | Offers an exceptional brand experience with impactful visuals, banners, and media assets. |
--&gt;


### Application PBCs

| NAME | DESCRIPTION | BENEFITS |
| --- | --- | --- |
| Back Office | The administration interface that allows you to manage all back-office tasks. In the Back Office, you can manage and create customer accounts and define who can access the Back Office. You can also keep track of all your internal processes including the management of your products, orders, customers and many more. | Keeps your back-end processes running efficiently, protects your data and administers all accounts. |
| Storefront | The out-of-the-box online shop application that includes all regular functionalities and workflows. You can use the Storefront as a boilerplate to kick-start your project. | Lets you easily start your online shop from our boilerplate solution. |

## App Composition Platform apps

&lt;div class=&quot;width-100&quot;&gt;

| APP | CATEGORY |
| --- | --- |
| [Vertex](/docs/pbc/all/tax-management/{{site.version}}/base-shop/third-party-integrations/vertex/vertex.html) | Tax compliance. |
| [Algolia](/docs/pbc/all/search/{{site.version}}/base-shop/third-party-integrations/algolia/integrate-algolia.html) | Search engine. |
| [Payone](/docs/pbc/all/payment-service-providers/payone/integrate-payone.html) | Payment service provider. |
| [Bazaarvoice](/docs/pbc/all/ratings-reviews/{{site.version}}/third-party-integrations/integrate-bazaarvoice.html) | Platform for user-generated content. |
| [Stripe](/docs/pbc/all/payment-service-provider/{{site.version}}/base-shop/third-party-integrations/stripe/stripe.html) |  Financial infrastructure platform. |

&lt;/div&gt;
</description>
            <pubDate>Wed, 29 Apr 2026 10:34:52 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/pbc.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/pbc.html</guid>
            
            
        </item>
        
        <item>
            <title>AI Commerce</title>
            <description>&lt;p&gt;AI Commerce brings AI-powered capabilities to your Spryker storefront and back office, reducing manual effort for buyers and shop operators, accelerating commerce workflows. Features are built on the &lt;code&gt;AiFoundation&lt;/code&gt; abstraction layer, so the underlying AI model can be swapped or configured per feature without changing application code.&lt;/p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;FEATURE&lt;/th&gt;
&lt;th&gt;DESCRIPTION&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;/docs/pbc/all/ai-commerce/latest/smart-pim.html&quot;&gt;Smart PIM&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Help catalog managers enrich product information directly in the Backoffice PIM. Get guided suggestions to speed up day-to-day catalog work, improve consistency across markets and languages, and keep full control through human review and auditability.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;/docs/pbc/all/ai-commerce/latest/visual-add-to-cart.html&quot;&gt;Visual Add to Cart&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Lets buyers upload a product image on the Quick Order page. AI recognizes the products in the image and pre-fills the order form with matching SKUs and quantities — enabling rapid bulk ordering without manual entry.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;/docs/pbc/all/ai-commerce/latest/backoffice-assistant.html&quot;&gt;Back Office Assistant&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;An AI-powered chat widget embedded in the Back Office. Admin users can ask natural language questions to navigate the Back Office, diagnose order issues, and create or update discounts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;/docs/pbc/all/ai-commerce/latest/search-by-image.html&quot;&gt;Search by Image&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Lets customers upload a photo to search for products. AI analyzes the image, identifies a search term, and redirects to search results or the first matching product page.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;who-benefits&quot;&gt;Who benefits&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ROLE&lt;/th&gt;
&lt;th&gt;BENEFIT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;B2B buyers&lt;/td&gt;
&lt;td&gt;Faster reordering from photos of shelves, product lists, or packaging. Find products by uploading a photo instead of searching by name.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Store operators&lt;/td&gt;
&lt;td&gt;Reduced support requests caused by manual order entry errors. Faster Back Office workflows through conversational AI assistance.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developers&lt;/td&gt;
&lt;td&gt;AI provider-agnostic integration — swap or configure models per feature via configuration.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
            <pubDate>Wed, 29 Apr 2026 10:34:52 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/ai-commerce/latest/ai-commerce.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/ai-commerce/latest/ai-commerce.html</guid>
            
            
        </item>
        
        <item>
            <title>Release notes 202602.0</title>
            <description>Spryker Cloud Commerce OS is an end-to-end solution for digital commerce. This document contains a business-level description of new features and improvements.

For information about installing Spryker, see [Getting started guide](/docs/dg/dev/development-getting-started-guide).

## B2B Business-Ready Commerce Experiences

### Product Attachments {% include badge.html type=&quot;feature&quot; %}

Introduces out-of-the-box Product Attachments capability commonly required in industrial B2B purchasing.

{% include carousel.html
images=&quot;https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/product_attachments_storefront_pdp.png||::https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/product_attachments_backoffice_pim.png||&quot;
%}

**Key capabilities**
- Back Office management of product-related documents (for example, datasheets, certificates, manuals).
- Provide external links to product attachments via data import.
- Display and download or view attachments on the product details page.

**Business benefits**
- Supporting buyers&apos; decisions by providing more detailed product information.
- Removes approval bottlenecks and shortens the path from product view to first transaction.

**Documentation**
- [Product Attachments overview](/docs/pbc/all/product-information-management/latest/base-shop/feature-overviews/product-feature-overview/product-attachments-overview.html)
- [Install the Product Attachments feature](/docs/pbc/all/product-information-management/latest/base-shop/install-and-upgrade/install-features/install-the-product-attachments-feature.html)

### Product &amp; Merchant Offer Availability Display {% include badge.html type=&quot;feature&quot; %}

Introduces native, configurable product and merchant offer availability display for B2B Commerce and Marketplace scenarios, reducing customization and increasing buyer confidence at the point of decision.

**Key capabilities**
- Native availability display on the product details page (PDP) and in the cart
- Configurable display logic:
  - Availability indicator only (for example Available / Out of Stock)
  - Exact stock quantity combined with indicator
  - Configuration option for the sort order of merchant offers in the B2B Marketplace
- Built on existing Spryker stock data structures

**Business benefits**
- Buyers see reliable availability information at the point of decision.
- Businesses no longer need custom implementations for basic stock visibility.
- Transparent stock visibility increases direct orders and reduces operational overhead.

**Documentation**
- [Product Availability Display feature overview](/docs/pbc/all/warehouse-management-system/latest/base-shop/product-availability-display-feature-overview)
- [Buy Box feature overview](/docs/pbc/all/offer-management/latest/marketplace/buy-box-feature-overview)

### Backoffice Configuration Framework {% include badge.html type=&quot;feature,early-access&quot; %}

Introduces a structured, extensible framework to expose business-relevant configuration directly in the Spryker Back Office without code changes or redeployments.

**Key capabilities**
- Structured Business Configuration via UI
  - Developers define configuration options in YAML once.
  - The framework automatically renders validated Back Office UI pages.
- Runtime Configuration Without Deployment
  - Configuration changes are applied at runtime, no code change, no pull request, no deployment required.
- Support for Out-of-the-Box and Custom Features. The framework works for:
  - Standard Spryker features
  - Project-specific customizations
- Built-in Validation &amp; Guardrails
  - Business users can only adjust explicitly defined and validated options, preventing misconfiguration.

**Business benefits**
- Faster Time to Change
  - Business teams adjust approved behaviors instantly, no development sprint required.
- Lower Total Cost of Change
  - Reduces repetitive engineering effort for configuration updates and eliminates custom UI builds per feature.
- Faster Experimentation
  - Test different configuration setups (for example display logic, marketplace sorting) without waiting for release cycles.

### B2B-only Mode Enablement

Reduces project setup time for customers and partners who want B2B Commerce only, without Marketplace complexity.

**Key capabilities**
- Added a **guideline and deployment script** to start the unified demo shop in a standardized **B2B Commerce–only mode**, reducing required manual cleanup and configuration.

**Business benefits**
- Faster project initialization for B2B-only projects.
- Lower implementation cost and reduced efforts.
- Clearer positioning and smoother kick-off experience.

**Documentation**
- [Uninstall the Marketplace from B2B Demo Marketplace](/docs/about/all/uninstall-marketplace-from-b2b-demo-marketplace)

### New Industrial Homepage Sample Data {% include badge.html type=&quot;improvement&quot; %}

The new sample data allows you to explore more realistic B2B Commerce journeys and capabilities without needing to import your own data.

**Key capabilities**
- Updated homepage content to industrial goods and services across key blocks (banners, featured categories, featured products, top sellers).

**Business benefits**
- More realistic demos that reflect real industrial buying journeys.
- Faster evaluations by showing realistic catalog and merchandising scenarios out of the box.
- Less manual demo preparation for partners and solution teams.

### UX &amp; Design Improvements for Storefront &amp; Back Office {% include badge.html type=&quot;improvement&quot; %}

Improves clarity, consistency, and perceived quality across core pages and navigation.

{% include carousel.html
   images=&quot;https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/Menu Icons.png||::https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/Empty_status_page.png||::https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/Toast_notifications.png||&quot;
%}

**Key capabilities**
- Redesigned the Back Office 404 page with clear recovery actions and consistent styling, removing technical error output for a smoother user experience.
- Improved empty states for Addresses, Orders, and Returns pages in storefront to guide users with clear next steps and better first-time usability.
- Updated navigation to Google Material Icons for visual consistency with the Merchant Portal.
- Replaced full-width banner of toast notifications with stacked, auto-dismissing toast notifications for lightweight, non-disruptive feedback.
- Fixed Back Office form validation errors showing untranslated message keys (restored translation rendering).

**Business benefits**
- Faster task completion and reduced confusion in Back Office operations.
- Better first-time experience for B2B customers on key storefront pages.
- Higher perceived product quality and consistency for enterprise users.
- Reduced support noise caused by unclear errors and untranslated validation messages.


### PunchOut: cXML Compatibility in Spryker API &lt;span class=&quot;inline-img&quot;&gt;![feature](https://spryker.s3.eu-central-1.amazonaws.com/docs/scos/user/intro-to-spryker/releases/release-notes/feature.png)&lt;/span&gt;

Enables standardized B2B PunchOut integrations via cXML support.

**Key capabilities**
- Support for **cXML (Commerce XML)** as an additional data exchange format in the Spryker API Platform.
- Documentation and guidance for implementing PunchOut integrations with external eProcurement systems.

**Business benefits**
- Enterprise-ready B2B integration  API Compatibility with leading procurement platforms.
- Simplified implementation of PunchOut scenarios for customers and partners.
- Stronger positioning in complex B2B commerce environments.

**Documentation**
- [PunchOut Development Plan](/docs/integrations/custom-building-integrations/punchout-development-plan)

## Connected, and AI-Enabled Platform

### Spryker AI Foundation: Operable, Structured, and Extensible AI Runtime {% include badge.html type=&quot;early-access,improvement&quot; %}

Enhances the AI Foundation runtime layer to make AI executions easier to operate at scale, safer to integrate into product code, and more extensible for evolving use cases.

**Key capabilities**
- Prompt responses now return **token usage** and **applied AI configuration details** (for example, provider/vendor, model, configuration name, and relevant parameters) for improved transparency and troubleshooting.
- Added **structured response support** aligned with **Spryker Transfers**, enabling validated, contract-based AI outputs rather than fragile free-text parsing.
- Introduced a supported **tool call extension mechanism** for AI Foundation, enabling standardized enrichment of tool call inputs/outputs without project-specific integration workarounds.

**Business benefits**
- Improved cost and performance control through token visibility and configuration traceability.
- More reliable production integrations through typed, validated AI outputs (reduced downstream breakage from phrasing changes).
- Lower long-term maintenance and support effort via a standardized extension mechanism for evolving AI use cases.

**Documentation**
- [AI Foundation](/docs/pbc/all/ai-foundation/latest/ai-foundation.html)
- [Install the AI Foundation module](/docs/dg/dev/ai/ai-foundation/ai-foundation-module.html)
- [Use AI tools with the AiFoundation module](/docs/dg/dev/ai/ai-foundation/ai-foundation-tool-support.html)
- [Use structured responses with the AiFoundation module](/docs/dg/dev/ai/ai-foundation/ai-foundation-transfer-response.html)

### Spryker AI Commerce: Agent Foundations and Smart PIM Improvements {% include badge.html type=&quot;early-access,improvement&quot; %}

Adds foundational capabilities for advanced agent workflows and improves the Back Office Smart PIM with safer, more reliable AI-assisted product description support.

**Key capabilities**
- **Conversation history** support to maintain context across interactions, enabling better multi-step workflows.
- Introduced a **workflow orchestration layer** for predictable multi-step AI executions, including structured transitions, error handling, and auditability.
- Back Office Smart PIM: **AI assistance for product descriptions** directly within abstract and concrete product create and edit pages:
  - Actions to **Translate content** and **Improve content**
  - Review-before-apply workflow to avoid accidental overwrites
- Backoffice Smart PIM: **Clear user feedback when AI is not configured or unavailable**:
  - Validates provider credentials before calling external AI services
  - Shows user-facing error messages instead of silent empty responses
  - Logs operator-friendly errors without exposing secrets
  - UI safeguard disables AI actions with an explanatory tooltip when AI is not configured

**Business benefits**
- Higher adoption and trust in AI features due to clear error states and safer interaction patterns.
- Faster catalog enrichment through translation and content improvement with less manual effort and fewer review loops.
- Foundation for advanced B2B agent scenarios through context continuity and orchestrated workflows.
- Improved governance and auditability through workflow execution traceability.

**Documentation**
- [Smart Product Management](/docs/pbc/all/product-information-management/latest/base-shop/third-party-integrations/smart-product-management/smart-product-management.html)
- [Install Smart Product Management](/docs/pbc/all/product-information-management/latest/base-shop/third-party-integrations/smart-product-management/install-smart-product-management.html)
- [Manage conversation history with the AiFoundation module](/docs/dg/dev/ai/ai-foundation/ai-foundation-conversation-history.html)
- [AI workflow orchestration with state machines](/docs/dg/dev/ai/ai-foundation/ai-foundation-workflow-state-machine.html)

### Spryker AI Dev SDK: Additional MCP Tools for Spryker-Aware AI Development {% include badge.html type=&quot;early-access,improvement&quot; %}

Expands MCP tooling to make Spryker context retrieval, module discovery, documentation grounding, and demo data manipulation faster and more reliable for AI-assisted development.

**Key capabilities**
- Added `getSprykerModuleMap` MCP tool to return **comprehensive module information**, including:
  - Paths and core API components (Facade, Client, Service, Config)
  - Available plugin interfaces and extension points
- Added `getSprykerModules` MCP tool to return a **simplified flat list** of unique module names for efficient discovery and reduced token usage.
- Added a **Spryker documentation** MCP tool supporting:
  - Docs web URL
  - GitHub tree URL for the markdown source
  - GitHub API URL for raw markdown retrieval
- Added **read-only database access** tooling for agents to retrieve required information without manual user intervention (SQL query input).
- Added MCP tools to accelerate **import/demo data workflows**:
  - CSV structure analysis (without loading full content)
  - CSV transform operations (update/replace/append)
  - Row deletion by filter criteria
  - ODS-to-CSV export per sheet (supporting Google Sheets → Spryker import pipelines)

**Business benefits**
- Faster and more accurate AI-assisted development through Spryker-aware context (module APIs, extension points, docs grounding).
- Reduced onboarding time and fewer integration mistakes for developers and agents.
- Improved productivity for solution teams by standardizing CSV/ODS workflows and reducing failed import cycles.
- Lower token usage and faster tool responses due to simplified module discovery outputs.

**Documentation**
- [AI Dev SDK Overview](/docs/dg/dev/ai/ai-dev/ai-dev-overview)
- [AI Dev MCP Server](/docs/dg/dev/ai/ai-dev/ai-dev-mcp-server)

### API Platform improvements {% include badge.html type=&quot;early-access,improvement&quot; %}

This release enhances API Platform capabilities to improve your developer experience and reduce manual configuration overhead.

**Key capabilities**
- Enable support for relationships in API Platform.
- Add support for custom validation constraints (FQCN-based) in schema definitions.
- Improve dependency resolution for API Platform packages.
- Add support for Code Buckets.
- Provide API test examples to help you adopt the features more easily.

**Business benefits**
- Generate and validate API resources more cleanly and consistently.
- Reduce the need for manual dependency fixes.
- Improve consistency in your API implementations.
- Accelerate onboarding and increase developer productivity.

**Documentation**
- [Validation Schemas](/docs/dg/dev/architecture/api-platform/validation-schemas.html)
- [Code Buckets](/docs/dg/dev/architecture/api-platform/code-buckets.html)
- [Relationships](/docs/dg/dev/architecture/api-platform/relationships.html)
- [API Test Examples](/docs/dg/dev/architecture/api-platform/testing.html)

### OMS New Visual User Experience {% include badge.html type=&quot;improvement&quot; %}

Spryker transforms the community-driven OMS visualizer into a fully validated and productized capability.

![Screenshot of the OMS visualizer showing order state machine transitions](https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/2026-OMS-visualizer.png)

**Key capabilities**
- Provides a streamlined visualization of complex Order State Machines (OMS).

**Business benefits**
- Enables faster OMS iteration cycles and improves clarity when you develop or validate OMS processes.
- Reduces the time you spend debugging OMS flows by providing better visibility and tooling support.

**Documentation**
- [Original Community Contribution](https://github.com/spryker-community/oms-visualizer)
- [Oms Visualizer Release](https://api.release.spryker.com/release-group/6358)

### Messaging and scheduling modernization {% include badge.html type=&quot;improvement&quot; %}

We introduced Symfony Messenger and Symfony Scheduler as modern, flexible alternatives to the current RabbitMQ adapter and scheduling mechanisms in Jenkins.

**Key capabilities**
- Feature toggle that lets you switch between RabbitMQ and Messenger without breaking compatibility.
- Migration path and supporting documentation to help you transition.
- Messenger becomes the default queue adapter.
- Scheduler lets you control the job schedule from within your application.

**Business benefits**
- Gain greater flexibility in queue transport configuration.
- Align scheduling with the Symfony ecosystem using a modern approach.

**Documentation**
- [Symfony Messenger](/docs/dg/dev/integrate-and-configure/integrate-symfony-messenger.html)
- [Symfony Scheduler](/docs/dg/dev/integrate-and-configure/integrate-symfony-scheduler.html)

### Secure handling of customer data in quote requests {% include badge.html type=&quot;improvement&quot; %}

This update improves the quote request storage mechanism to ensure that the system does not unnecessarily persist sensitive customer data in version records.

Previously, the `spy_quote_request_version` table stored the complete quote JSON, which could include full company customer data, including encrypted passwords. Although the passwords were encrypted, storing them outside the dedicated customer table increased the risk of exposure and did not follow the principle of data minimization.

**Key capabilities**
- Removes unnecessary storage of sensitive customer data, such as encrypted passwords, from the `spy_quote_request_version` table.
- Ensures that customer credentials remain stored exclusively in the `spy_customer` table.
- Improves secure data handling in quote request versioning flows that the Storefront triggers.

**Business benefits**
- Reduces the risk of confidential data exposure.
- Strengthens compliance with secure data handling and data minimization principles.
- Improves overall database hygiene and reduces the attack surface.

**Documentation**
- [Quote Request](https://api.release.spryker.com/release-group/6300)

### Platform &amp; Tooling Upgrades {% include badge.html type=&quot;improvement&quot; %}

We have updated critical application and service components to long-term supported versions to ensure continued stability, performance, and compatibility.

**Key capabilities**
- Upgraded PHPUnit to version 12 (full PHP 8.3 support, improved test data handling).
- Upgraded PHPStan to version 2.x to reduce memory consumption and significantly improve performance.
- Upgraded Angular to the latest supported major version 20.

**Business benefits**
- Faster CI pipelines and reduced waiting times for static analysis.
- Continued alignment with PHP ecosystem and Angular support lifecycles.
  - Resolved a vulnerability in `@angular/common` affecting Spryker applications. The issue (CVE-2025-66035) allowed potential XSRF token leakage via protocol-relative URLs in Angular HTTP clients, potentially exposing CSRF tokens to attacker-controlled domains.
- Improved quality assurance and development tooling performance across projects.

**Documentation**
- [Upgrade to Angular 20](https://docs.spryker.com/docs/dg/dev/upgrade-and-migrate/upgrade-to-angular-20.html)
- [Release unlocking the new PHPUnit version](https://api.release.spryker.com/release-group/6334)
- Spryker is fully compatible with PHPStan 2.x, update it at your own schedule.

### Quality, Performance &amp; Stability Fixes {% include badge.html type=&quot;improvement&quot; %}

This release resolves several performance bottlenecks and technical inconsistencies identified in customer projects.

**Key capabilities**
- Improved Stock Data Import performance by removing the usage of `\ProductAbstractCheckExistenceStep` and `\ProductConcreteCheckExistenceStep`, which eliminates unnecessary full database loads.
- Preserved correct HTTP error codes by returning 4xx responses for expected application errors, such as invalid cart operations, instead of 500.
- Optimized customer session validation by removing resource-intensive password hash checks.
- Stabilized OpenTelemetry monitoring and New Relic instrumentation to prevent memory issues and improve trace grouping for Zed and Gateway traffic.
- Fixed concrete product publishing and product filter handling, including whitelist-aware category suggestions and hidden facets, to restore complete and consistent search results.
- Corrected the Data Import CSV reader configuration so that offset and limit options work as expected for partial imports.
- Restored Back Office form validation translations and eliminated redundant SQL execution in category rules.
- Improved cart behavior in the Glue API by merging guest carts with product bundles on login and introducing SKU-level quantity restriction plugins.

**Business benefits**
- Improved backend performance and reduced database and CPU load.
- Delivered more reliable and predictable product search, filtering, and category navigation for end users.
- Enabled more stable imports and storefront builds with safer customizations and improved dependency management.
- Improved Back Office and cart usability to reduce operational overhead and user friction.
- Add guidance to the public Spryker documentation on how to adopt the Cypress boilerplate.

**Documentation**
- See [Spryker Releases](https://api.release.spryker.com/release-history) or use `composer` to update all packages.
- [E2E Testing with Cypress](/docs/dg/dev/guidelines/testing-guidelines/cypress-testing.html)

### Architecture Guidelines &lt;span class=&quot;inline-img&quot;&gt;![improvement](https://spryker.s3.eu-central-1.amazonaws.com/docs/scos/user/intro-to-spryker/releases/release-notes/improvement.png)&lt;/span&gt;

A set of practical, reusable guidelines to reduce delivery risk, prevent recurring implementation pitfalls, and standardize engineering practices across Spryker projects.

**Key capabilities**
- **APM monitoring and troubleshooting using New Relic**
  - Standardized end-to-end troubleshooting workflow (metrics → transactions → DB queries → traces).
  - Clear mapping of New Relic entities to Spryker applications (Yves, Zed, Glue, Merchant Portal).
  - Practical examples for diagnosing common performance issues.
- **Performance best practices: common challenges and optimization strategies**
  - Documented top recurring performance pitfalls from real projects (symptoms, root cause patterns, proven optimizations).
  - Guidance on recognizing issues via response time, query patterns, and logs.
- **How to start a Spryker project**
  - Step-by-step setup guidance covering project structure, CI/CD basics, team practices, and quality tooling.
  - Focus on &quot;must-do&quot; principles to avoid rework and long-term quality degradation.

**Business benefits**
- Faster onboarding for partners and new project teams through standardized, actionable guidance.
- Reduced escalation rate by addressing known recurring delivery and performance pitfalls early.
- Improved project consistency and upgradeability through repeatable architecture and documentation patterns.
- Better diagnosability and prevention of performance degradation with a shared troubleshooting methodology.

**Documentation**
- [APM — New Relic based troubleshooting](/docs/dg/dev/guidelines/performance-guidelines/apm-newrelic-based-troubleshooting.html)
- [Perfromance best practices](/docs/dg/dev/guidelines/performance-guidelines/performance-guidelines.html)
- [Updated how to start Spryker project](/docs/dg/dev/development-getting-started-guide.html)

### Architecture as Code for Spryker projects &lt;span class=&quot;inline-img&quot;&gt;![improvement](https://spryker.s3.eu-central-1.amazonaws.com/docs/scos/user/intro-to-spryker/releases/release-notes/improvement.png)&lt;/span&gt;

Live, version-controlled architecture documentation using industry standards that scales with your codebase. Enables team collaboration, decision traceability, and onboarding without custom tooling or specialized training.

**Key capabilities**
- Ready-to-use architecture templates for living, version-controlled architecture documentation that evolves with your code, based on arc42 (12 sections) and the C4 model (4-level visualization).
- Traceable architectural decision templates through Solution Designs (RFC-style exploration) and ADRs.
- Diagrams as code using Mermaid and PlantUML, with real examples for automated validation, generation, and AI analysis.

**Business benefits**
- Faster onboarding - with globally-recognized standards and all needed architecture documentation in one place - your code
  - Better decision making - RFC-style exploration and full decision history eliminate tribal knowledge
  - Alignment with business - Capture project requirements, trade-offs before implementation, ensuring delivery matches intent. Evolve further with architecture decision records  and Solution designs
  - AI-ready format - Markdown and code-based diagrams enable intelligent automation and documentation generation

**Documentation**
- [Architecture as a Code](/docs/dg/dev/architecture/architecture-as-code.html)

### ERP Integration Template &lt;span class=&quot;inline-img&quot;&gt;![improvement](https://spryker.s3.eu-central-1.amazonaws.com/docs/scos/user/intro-to-spryker/releases/release-notes/improvement.png)&lt;/span&gt;

Provides a standardized foundation for building ERP integrations without starting from scratch.

**Key capabilities**
- Reusable module structure (Client and Shared layers) with transfer object definitions.
- Pre-built base classes (`BaseRequest`, `BaseRequestBuilder`) for:
  - Request handling and timeout configuration
  - Headers and authentication
  - Logging and error management
- Request/response mapper pattern for ERP-specific format transformations.
- Guzzle client configuration guidance with environment-specific credentials and connection setup.

**Business benefits**
- Faster ERP integration development with reduced boilerplate.
- Consistent architecture across projects and ERP systems.
- Lower risk of integration defects due to standardized logging and error handling.
- Improved maintainability and onboarding for new ERP integrations.

**Documentation**
- [ERP Integration Template](/docs/integrations/custom-building-integrations/erp-integration-template.html)

### Payment Integration Template (PSP Template) &lt;span class=&quot;inline-img&quot;&gt;![improvement](https://spryker.s3.eu-central-1.amazonaws.com/docs/scos/user/intro-to-spryker/releases/release-notes/improvement.png)&lt;/span&gt;

Delivers a production-ready template repository for building payment service provider (PSP) integrations.

**Key capabilities**
- Covers all mandatory integration touchpoints with the SCCOS that must be considered when integrating a payment provider (business logic, configurations, OMS, frontend forms)  and payment lifecycle handling, with practical implementation examples.
- Support for core payment flows: **Authorize → Capture → Cancel**.
- Two payment method templates (for example Credit Card, Invoice) including:
  - OMS state machines for synchronous and asynchronous authorization.
- Webhook infrastructure:
  - Payload logging
  - Signature validation
  - Route provider setup
- Data import configuration with payment method CSV templates and glossary translations (EN, DE).
- Automated module renaming and setup guidance to accelerate project adoption.
- Comprehensive integration checklist to ensure no required system part is missed during implementation.

**Business benefits**
- Reduced development time for new PSP integrations
- Consistent payment architecture and OMS alignment across projects.
- Improved reliability through standardized webhook and lifecycle handling.
- Clear separation of module developer and project integrator responsibilities.

**Documentation**
- [PSP Integration Template](/docs/integrations/custom-building-integrations/psp-integration-template.html)

### New Algolia Eco-Module Integration &lt;span class=&quot;inline-img&quot;&gt;![improvement](https://spryker.s3.eu-central-1.amazonaws.com/docs/scos/user/intro-to-spryker/releases/release-notes/improvement.png)&lt;/span&gt;

Replaces the legacy Algolia App model with a code-visible eco-module.

**Key capabilities**
- New Algolia integration as a standard Spryker eco-module.
- Full code visibility and extensibility for customers and partners.
- Support for current Algolia Search license–related features.
- Updated documentation for integration and customization.

**Business benefits**
- Increased flexibility and customization options.
- Reduced dependency on black-box App Spryker support and evolution implementations.
- Better alignment with project-level architecture and extension patterns.

**Documentation**
- [Integrate Algolia](/docs/pbc/all/search/latest/base-shop/third-party-integrations/algolia/integrate-algolia.html)

## Efficient and Flexible Cloud Foundation

### Cloud Self-Service Portal update {% include badge.html type=&quot;improvement&quot; %}

The Cloud Self-Service Portal is now available on a new platform that improves usability and accelerates value delivery.

{% include carousel.html
   images=&quot;
   https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/cloud-hub1.png||::
   https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/cloud-hub2.png||::
   https://spryker.s3.eu-central-1.amazonaws.com/docs/About/Releases/release-notes-202602/cloud-hub3.png||&quot;
%}

**Key capabilities**
- Spryker has moved the Cloud Self-Service Portal to a new platform to provide a better user experience and faster value delivery.
- In the new portal, you can access centralized Single Sign-On (SSO) management.

**Business benefits**
- Provides a structured migration path to Single Sign-On (SSO) to help you simplify access management.

**Portal access**
- [Customer Portal](https://portal.spryker.com/)

### RabbitMQ 4.1 rollout {% include badge.html type=&quot;improvement&quot; %}

This update completes the rollout of RabbitMQ 4.1 across all platform environments.

**Key capabilities**
- Upgrade to RabbitMQ 4.1 for improved messaging infrastructure.
- Platform-wide rollout to ensure consistency across environments.

**Business benefits**
- Improved stability and performance of asynchronous processing.
- Enhanced scalability for event-driven workloads.
- Reduced operational risk through alignment with the latest supported messaging version.

**Documentation**
- [Docker SDK service configuration](/docs/dg/dev/integrate-and-configure/configure-services.html)
- [System Requirements](/docs/dg/dev/system-requirements/latest/system-requirements.html)

### Security RSS feed: Docker image updates {% include badge.html type=&quot;improvement&quot; %}

This update integrates Docker image security release notes into the official Spryker security RSS feed, ensuring timely notifications for infrastructure updates.

**Key capabilities**
- RSS Feed Integration: Docker image security releases are now automatically published to the security RSS stream (/feed-security.xml)
- Automated Visibility: Real-time visibility of image-related security patches alongside standard application news.

**Business benefits**
- Improved Security Posture: Ensures DevOps and Security teams are immediately alerted to infrastructure-level vulnerabilities and patches.
- Streamlined Compliance: Easier tracking and auditing of container image versions through a centralized, standardized feed.
- Proactive Maintenance: Reduces the window of exposure by eliminating the need to manually check for image updates.

**Documentation**
- [Spryker Security RSS Feed](/feed-security.xml)
- [Release notes](/docs/about/all/releases/product-and-code-releases.html)
</description>
            <pubDate>Wed, 29 Apr 2026 09:20:10 +0000</pubDate>
            <link>https://docs.spryker.com/docs/about/all/releases/release-notes-202602.0.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/about/all/releases/release-notes-202602.0.html</guid>
            
            
        </item>
        
        <item>
            <title>Getting started with APIs</title>
            <description>&lt;div class=&quot;content_box&quot;&gt;

Spryker&apos;s API is a dedicated application layer within the Spryker Cloud Commerce OS. It&apos;s designed to provide API endpoints, process requests, and communicate with other parts of the system to manage data.  Think of it as the primary interface for any external system, custom frontend, or digital touchpoint that needs to interact with your Spryker-powered commerce platform.  Its main purpose is to enable headless commerce strategies, allowing you to build unique customer experiences and integrate seamlessly with a multitude of channels. Spryker&apos;s API framework offers the following types of API applications, each tailored for different use cases.

&lt;/div&gt;

&lt;div class=&quot;grid_container&quot;&gt;
  &lt;div class=&quot;cst_cards_2&quot;&gt;
    &lt;div class=&quot;cst_card&quot;&gt;
      &lt;div class=&quot;cst_card_title&quot;&gt;Storefront API&lt;/div&gt;
      &lt;div class=&quot;cst_card_desc&quot;&gt;Storefront API is designed for consumers and customer-facing integrations. It&apos;s the API layer that powers web shops, mobile apps, marketplaces, and other client-facing systems. It is based on REST API and follows JSON:API conventions. Learn about customer-facing API endpoints for building headless commerce experiences, mobile apps, and custom storefronts.&lt;/div&gt;
      &lt;a class=&quot;cst_card_button&quot; href=&quot;/docs/integrations/spryker-glue-api/storefront-api/storefront-api.html&quot;&gt;Learn more&lt;/a&gt;
    &lt;/div&gt;
    &lt;br&gt;
    &lt;div class=&quot;cst_card&quot;&gt;
      &lt;div class=&quot;cst_card_title&quot;&gt;Backend API&lt;/div&gt;
      &lt;div class=&quot;cst_card_desc&quot;&gt;Backend API is designed for admins and system-to-system communication. Tailored for backend processes, administrative tools, or integrations with enterprise systems, such as ERP or CRM. Technically it is multi-format, but REST API is shipped out-of-the-box. A key advantage is its direct access to Spryker&apos;s business logic layer (Facades). Discover administrative API endpoints for system integration, ERP connections, and backend operations with direct facade access.&lt;/div&gt;
      &lt;a class=&quot;cst_card_button&quot; href=&quot;/docs/integrations/spryker-glue-api/backend-api/backend-api.html&quot;&gt;Learn more&lt;/a&gt;
    &lt;/div&gt;
    &lt;br&gt;
    &lt;div class=&quot;cst_card&quot;&gt;
      &lt;div class=&quot;cst_card_title&quot;&gt;Spryker API Strategy for 2026&lt;/div&gt;
      &lt;div class=&quot;cst_card_desc&quot;&gt;Spryker is evolving its API strategy by introducing **API Platform–based integration** as a &lt;b&gt;new, strategic integration layer&lt;/b&gt;, while continuing to &lt;b&gt;fully support existing Glue APIs&lt;/b&gt;.&lt;/div&gt;
      &lt;a class=&quot;cst_card_button&quot; href=&quot;/docs/integrations/spryker-glue-api/getting-started-with-apis/api-strategy.html&quot;&gt;Learn more&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

</description>
            <pubDate>Wed, 29 Apr 2026 08:50:59 +0000</pubDate>
            <link>https://docs.spryker.com/docs/integrations/spryker-glue-api/getting-started-with-apis/getting-started-with-apis.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/integrations/spryker-glue-api/getting-started-with-apis/getting-started-with-apis.html</guid>
            
            
        </item>
        
    </channel>
</rss>
