<?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>Fri, 24 Apr 2026 12:53:48 +0000</lastBuildDate>
        <generator>Jekyll v4.2.2</generator>
        
        
        <item>
            <title>Troubleshooting API Platform</title>
            <description>This document provides solutions to common issues when working with API Platform in Spryker.

## Generation issues

### Resources not generating

**Symptom:** Running `docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate` completes but no resources are created.

**Possible causes:**

1. **Schema file location is incorrect**

   ```bash
   ❌ src/Pyz/Glue/Customer/api/customers.resource.yml
   ✅ src/Pyz/Glue/Customer/resources/api/backend/customers.resource.yml
   ```

2. **API type not configured**

   Check `config/{APPLICATION}/packages/spryker_api_platform.php`:

   ```php
   $containerConfigurator-&gt;extension(&apos;spryker_api_platform&apos;, [
       &apos;api_types&apos; =&gt; [
           &apos;backend&apos;,  // Must match directory name
       ],
   ]);
   ```

3. **Bundle not registered**

   Verify `config/{APPLICATION}/bundles.php` includes:

   ```php
   SprykerApiPlatformBundle::class =&gt; [&apos;all&apos; =&gt; true],
   ```

**Solution:**

```bash
# Debug to see what&apos;s being discovered
docker/sdk cli glue  api:debug --list

# Check schema validation
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate --validate-only

# Force regeneration
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate --force
```

### Wrong modules are being generated

**Symptom:** The generator picks up schemas from modules you want routed to a different application, or misses modules you expect to see.

**Possible causes:**

1. **Two applications share the same source tree.** For example, a project runs the legacy Glue REST stack next to the new API Platform storefront, and both apps scan `src/Spryker/*`.
2. **A module is half-migrated** and has schemas in `resources/api/{apiType}` that should not yet be exposed.

**Solution:** Use the four filter options exposed by `SprykerApiPlatformConfig` in `config/{APPLICATION}/packages/spryker_api_platform.php`:

- `includedModulePatterns([&apos;*RestApi&apos;])` — allowlist based on module name, `fnmatch` patterns.
- `excludedModulePatterns([&apos;*RestApi&apos;])` — blocklist based on module name.
- `includedPathFragments([&apos;src/Pyz/&apos;])` — allowlist based on literal substrings of the schema file&apos;s real path.
- `excludedPathFragments([&apos;src/Spryker/AuthRestApi/resources/api/&apos;])` — blocklist based on literal substrings of the schema file&apos;s real path.

Blocklists always win over allowlists. For the full list of options and evaluation order, see [API Platform Configuration — Spryker-specific bundle configuration](/docs/dg/dev/architecture/api-platform/configuration.html#spryker-specific-bundle-configuration).

### Schema validation errors

**Symptom:** Generation fails with schema validation errors.

**Common errors:**

```bash
# Error: Invalid operation type
❌ operations:
    - type: CREATE

✅ operations:
    - type: Post

# Error: Invalid property type
❌ type: int
✅ type: integer

# Error: Missing resource name
❌ resource:
    shortName: Customer

✅ resource:
    name: Customers
    shortName: Customer
```

**Solution:**

1. Check schema against examples in documentation
2. Use `--validate-only` flag for detailed validation:

   ```bash
   docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate --validate-only
   ```

3. Inspect merged schema:

   ```bash
   docker/sdk cli glue  api:debug resource-name --show-merged
   ```

## Runtime issues

### Provider/Processor not found

**Symptom:**

```bash
Error: Class &quot;Pyz\Glue\Customer\Api\Backend\Provider\CustomerBackendProvider&quot; not found
```

**Possible causes:**

1. Class doesn&apos;t exist or namespace is wrong
2. Not registered in the Dependency Injection container
3. Typo in the schema file

**Solution:**

1. Verify the class exists and namespace matches:

   ```php
   namespace Pyz\Glue\Customer\Api\Backend\Provider;

   class CustomerBackendProvider implements ProviderInterface
   ```

2. Ensure services are auto-discovered in `ApplicationServices.php`:

   ```php
   $services-&gt;load(&apos;Pyz\\Glue\\&apos;, &apos;../../../src/Pyz/Glue/&apos;);
   ```

3. Check class name in the resource schema file of the module matches exactly:

   ```yaml
   provider: &quot;Pyz\\Glue\\Customer\\Api\\Backend\\Provider\\CustomerBackendProvider&quot;
   ```

### Validation not working

**Symptom:** API accepts invalid data despite validation rules.

**Possible causes:**

1. Validation schema file not found
2. Wrong operation name in validation schema
3. Validation groups not matching

**Solution:**

1. Ensure validation file exists:

   ```bash
   ✅ resources/api/backend/customers.validation.yml
   ```

2. Match operation names to HTTP methods:

   ```yaml
   post:      # For POST /customers
     email:
       - NotBlank

   patch:     # For PATCH /customers/{id}
     email:
       - Optional:
           constraints:
             - Email
   ```

3. Check generated resource class (for example `Generated\Api\Storefront\CustomersStorefrontResource`) has validation attributes:

   ```php
   #[Assert\NotBlank(groups: [&apos;customers:create&apos;])]
   #[Assert\Email(groups: [&apos;customers:create&apos;])]
   public ?string $email = null;
   ```

### API documentation UI not displaying correctly

**Symptom:** When accessing the root URL of your API application, you see:
- Missing styles/CSS
- Broken JavaScript functionality
- Plain HTML without formatting
- &quot;Failed to load resource&quot; errors in browser docker/sdk cli glue 

**Cause:** Assets were not installed after API Platform integration.

**Solution:**

Run the appropriate assets:install command for your application:

### For Glue application

```bash
docker/sdk cli glue assets:install public/Glue/assets  --symlink
```

### For GlueStorefront

```bash
docker/sdk cli GLUE_APPLICATION=GLUE_STOREFRONT glue assets:install public/GlueStorefront/assets/  --symlink
```

### For GlueBackend

```bash
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue assets:install public/GlueBackend/assets/  --symlink
```

Then verify the documentation UI loads correctly by visiting the root URL:
- Storefront: `https://glue-storefront.mysprykershop.com/`
- Backend: `https://glue-backend.mysprykershop.com/`

{% info_block warningBox &quot;Required after integration&quot; %}

The `assets:install` command must be run after integrating API Platform and whenever API Platform assets are updated. This is a required step documented in [How to integrate API Platform](/docs/dg/dev/upgrade-and-migrate/integrate-api-platform.html).

{% endinfo_block %}

### 404 Not Found for API endpoints

**Symptom:** API requests return 404.

**Possible causes:**

1. Router not configured
2. Routes not loaded
3. Wrong URL format

**Solution:**

1. Verify `SymfonyFrameworkRouterPlugin` is registered:

   ```php
   // RouterDependencyProvider
   protected function getRouterPlugins(): array
   {
       return [
           new GlueRouterPlugin(),
           new SymfonyFrameworkRouterPlugin(), // Must be present
       ];
   }
   ```

2. Check API documentation for correct URLs:

   ```bash
   Storefront: https://glue-storefront.mysprykershop.com/
   Backend: https://glue-backend.mysprykershop.com/
   ```

   The interactive API documentation is available at the root URL of each application.

3. Use correct URL format:

   ```bash
   ❌ /api/v1/customers
   ✅ /customers
   ```

### Pagination not working

**Symptom:** All results returned instead of paginated response.

**Solution:**

1. Enable pagination in the schema file of the defining module:

   ```yaml
   resource:
     paginationEnabled: true
     paginationItemsPerPage: 10
   ```

2. Return `PaginatorInterface` from provider:

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

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

3. Use pagination query parameters:

   ```bash
   GET /customers?page=2&amp;itemsPerPage=20
   ```

### Client cannot change items per page

**Symptom:** The `itemsPerPage` query parameter is ignored.

**Solution:**

Enable client-side items-per-page control and set a maximum limit in the resource schema:

```yaml
resource:
  paginationEnabled: true
  paginationItemsPerPage: 10
  paginationClientItemsPerPage: true
  paginationMaximumItemsPerPage: 100
```

Without `paginationClientItemsPerPage: true`, the `itemsPerPage` query parameter has no effect. The `paginationMaximumItemsPerPage` option prevents clients from requesting excessively large pages.

### Client cannot disable pagination

**Symptom:** The `pagination=false` query parameter is ignored and results are still paginated.

**Solution:**

Enable client-side pagination control in the resource schema:

```yaml
resource:
  paginationClientEnabled: true
```

Without `paginationClientEnabled: true`, the `pagination` query parameter has no effect.

For a full reference of all pagination options, see [Resource Schemas — Pagination](/docs/dg/dev/architecture/api-platform/resource-schemas.html#pagination).

## Dependency Injection issues

### Services not autowired

**Symptom:**

```bash
Cannot autowire service &quot;CustomerBackendProvider&quot;: argument &quot;$customerFacade&quot;
references class &quot;CustomerFacadeInterface&quot; but no such service exists.
```

**Solution:**

1. Register facade in the respective applications `ApplicationServices.php`:

   ```php
   use Pyz\Zed\Customer\Business\CustomerFacadeInterface;
   use Pyz\Zed\Customer\Business\CustomerFacade;

   $services-&gt;set(CustomerFacadeInterface::class, CustomerFacade::class);
   ```

2. Ensure constructor uses interface type hints:

   ```php
   public function __construct(
       private CustomerFacadeInterface $customerFacade,  // ✅ Interface
   ) {}
   ```

## Performance issues

### Slow API responses

**Symptom:** API endpoints respond slowly.

**Solution:**

1. Enable Symfony cache:

   ```bash
   docker/sdk cli glue  cache:warmup
   ```

2. Use pagination for collections
3. Optimize database queries in Provider
4. Use API Platform&apos;s built-in caching features

## Development tips

### Debugging schema merging

See which schemas contribute to final resource:

```bash
docker/sdk cli glue  api:debug customers --api-type=backend --show-sources
```

Output:

```bash
Source Files (priority order):
  ✓ vendor/spryker/customer/resources/api/backend/customers.resource.yml (CORE)
  ✓ src/SprykerFeature/CRM/resources/api/backend/customers.resource.yml (FEATURE)
  ✓ src/Pyz/Glue/Customer/resources/api/backend/customers.resource.yml (PROJECT)
```

### Inspecting generated code

View the generated resource class:

```bash
cat src/Generated/Api/Backend/CustomersBackendResource.php
```

Check for:
- Correct property types
- Validation attributes
- API Platform metadata

### Testing with dry-run

Preview generation without writing files:

```bash
docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:generate --dry-run
```

## Getting help

If you encounter issues not covered here:

1. **Check logs:**

   ```bash
   tail -f var/log/application.log
   tail -f var/log/exception.log
   ```

2. **Enable debug mode:**

   ```php
   // config/{APPLICATION}/packages/spryker_api_platform.php
   $containerConfigurator-&gt;extension(&apos;spryker_api_platform&apos;, [
       &apos;debug&apos; =&gt; true,
   ]);
   ```

3. **Validate environment:**

   ```bash
   php -v  # Check PHP version (8.1+)
   composer show | grep api-platform
   docker/sdk cli glue  debug:container | grep -i api
   ```

4. **Common error patterns:**

| Error | Likely cause | Solution |
|-------|--------------|----------|
| `Class not found` | Autoloading issue | Run `composer dump-autoload` |
| `Service not found` | DI configuration | Check `ApplicationServices.php` |
| `Route not found` | Router not configured | Add `SymfonyFrameworkRouterPlugin` |
| `Validation failed` | Schema mismatch | Regenerate with `--force` |
| `Cache is stale` | Outdated cache | Run `cache:clear` |
| API docs UI broken/unstyled | Assets not installed | Run `docker/sdk cli glue /glue assets:install` |

## Next steps

- [API Platform](/docs/dg/dev/architecture/api-platform.html) - Overview and concepts
- [How to integrate API Platform](/docs/dg/dev/upgrade-and-migrate/integrate-api-platform.html) - Setup guide
- [API Platform Enablement](/docs/dg/dev/architecture/api-platform/enablement.html) - Creating resources
- [Resource Schemas](/docs/dg/dev/architecture/api-platform/resource-schemas.html) - Resource schema reference
- [Validation Schemas](/docs/dg/dev/architecture/api-platform/validation-schemas.html) - Validation schema reference
- [API Platform Testing](/docs/dg/dev/architecture/api-platform/testing.html) - Testing guide
</description>
            <pubDate>Fri, 24 Apr 2026 12:53:30 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/architecture/api-platform/troubleshooting.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/architecture/api-platform/troubleshooting.html</guid>
            
            
        </item>
        
        <item>
            <title>API Platform Configuration</title>
            <description>&lt;p&gt;Spryker uses &lt;a href=&quot;https://api-platform.com/docs/core/configuration/#symfony-configuration&quot;&gt;API Platform’s configuration options&lt;/a&gt; with Spryker-specific adaptations for PHP-based configuration and environment control.&lt;/p&gt;
&lt;h2 id=&quot;configuration-file-locations&quot;&gt;Configuration file locations&lt;/h2&gt;
&lt;p&gt;Configuration files are located in application-specific directories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GlueBackend:&lt;/strong&gt; &lt;code&gt;config/GlueBackend/packages/api_platform.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GlueStorefront:&lt;/strong&gt; &lt;code&gt;config/GlueStorefront/packages/api_platform.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Glue:&lt;/strong&gt; &lt;code&gt;config/Glue/packages/api_platform.php&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;spryker-specific-differences&quot;&gt;Spryker-specific differences&lt;/h2&gt;
&lt;h3 id=&quot;php-configuration-instead-of-yaml&quot;&gt;PHP configuration instead of YAML&lt;/h3&gt;
&lt;p&gt;Spryker uses PHP configuration with Symfony’s type-safe configuration objects instead of YAML files:&lt;/p&gt;
&lt;div class=&quot;language-php 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;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Symfony\Config\ApiPlatformConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ApiPlatformConfig&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Configuration here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;environment-variable-for-conditional-settings&quot;&gt;Environment variable for conditional settings&lt;/h3&gt;
&lt;p&gt;The configuration function receives an &lt;code&gt;$env&lt;/code&gt; parameter for environment-specific behavior:&lt;/p&gt;
&lt;div class=&quot;language-php 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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ApiPlatformConfig&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Enable developer tools only in development&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;dockerdev&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enableSwagger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enableSwaggerUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enableReDoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enableDocs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Common environment values: &lt;code&gt;prod&lt;/code&gt;, &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;dockerdev&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;configuration-examples&quot;&gt;Configuration examples&lt;/h2&gt;
&lt;h3 id=&quot;disable-swaggerui-in-production&quot;&gt;Disable SwaggerUI in production&lt;/h3&gt;
&lt;p&gt;Spryker shows the SwaggerUI only in development environments by default. This can be configured with:&lt;/p&gt;
&lt;div class=&quot;language-php 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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;dockerdev&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enableSwagger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enableSwaggerUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enableReDoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enableDocs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;disable-doctrine-integration&quot;&gt;Disable Doctrine integration&lt;/h3&gt;
&lt;p&gt;Spryker does not use Doctrine with API Platform:&lt;/p&gt;
&lt;div class=&quot;language-php 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;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;doctrine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;doctrineMongodbOdm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;configure-resource-mapping-paths&quot;&gt;Configure resource mapping paths&lt;/h3&gt;
&lt;p&gt;Specify where API Platform discovers resource classes. By default, only the generated resource directory is configured:&lt;/p&gt;
&lt;div class=&quot;language-php 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;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;%kernel.project_dir%/src/Generated/Api/Backend&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;add-custom-resource-paths&quot;&gt;Add custom resource paths&lt;/h3&gt;
&lt;p&gt;To use native API Platform resources alongside generated resources, add your directories to the mapping paths:&lt;/p&gt;
&lt;div class=&quot;language-php 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;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;%kernel.project_dir%/src/Generated/Api/Backend&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;%kernel.project_dir%/src/Pyz/Glue/*/Api/Backend/Resource&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;API Platform scans all configured paths for PHP classes with &lt;code&gt;#[ApiResource]&lt;/code&gt; attributes. Generated and manually created resources coexist without conflict.&lt;/p&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;Keep the generated path&lt;/div&gt;
&lt;p&gt;Always keep the &lt;code&gt;src/Generated/Api/{ApiType}&lt;/code&gt; path in the list. Removing it disables all YAML-generated resources.&lt;/p&gt;
&lt;/div&gt;&lt;/section&gt;
&lt;p&gt;For a complete guide on creating native resources, see &lt;a href=&quot;/docs/dg/dev/architecture/api-platform/native-api-platform-resources.html&quot;&gt;Native API Platform Resources&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;set-pagination-defaults&quot;&gt;Set pagination defaults&lt;/h3&gt;
&lt;div class=&quot;language-php 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;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;paginationItemsPerPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pagination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pageParameterName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;page&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;itemsPerPageParameterName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;itemsPerPage&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;These global defaults apply to all resources. Individual resources can override pagination behavior using per-resource options such as &lt;code&gt;paginationEnabled&lt;/code&gt;, &lt;code&gt;paginationItemsPerPage&lt;/code&gt;, &lt;code&gt;paginationMaximumItemsPerPage&lt;/code&gt;, &lt;code&gt;paginationClientEnabled&lt;/code&gt;, and &lt;code&gt;paginationClientItemsPerPage&lt;/code&gt; in their YAML schema files. See &lt;a href=&quot;/docs/dg/dev/architecture/api-platform/resource-schemas.html#pagination&quot;&gt;Resource Schemas — Pagination&lt;/a&gt; for details.&lt;/p&gt;
&lt;h3 id=&quot;configure-supported-formats&quot;&gt;Configure supported formats&lt;/h3&gt;
&lt;div class=&quot;language-php 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;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;formats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;jsonapi&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mime_types&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;application/vnd.api+json&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;formats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;jsonld&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mime_types&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;application/ld+json&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$apiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;formats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;xml&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mime_types&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;application/xml&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;configure-security&quot;&gt;Configure security&lt;/h3&gt;
&lt;p&gt;Security is configured in a separate &lt;code&gt;security.php&lt;/code&gt; file. For details, see &lt;a href=&quot;/docs/dg/dev/upgrade-and-migrate/integrate-api-platform-security.html&quot;&gt;How to integrate API Platform Security&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;complete-configuration-reference&quot;&gt;Complete configuration reference&lt;/h2&gt;
&lt;p&gt;For all available configuration options and their details, refer to the &lt;a href=&quot;https://api-platform.com/docs/core/configuration/#symfony-configuration&quot;&gt;API Platform Symfony Configuration documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The PHP method names in &lt;code&gt;ApiPlatformConfig&lt;/code&gt; correspond directly to the YAML keys in the official documentation.&lt;/p&gt;
&lt;h2 id=&quot;spryker-specific-bundle-configuration&quot;&gt;Spryker-specific bundle configuration&lt;/h2&gt;
&lt;p&gt;In addition to the upstream &lt;code&gt;ApiPlatformConfig&lt;/code&gt;, Spryker ships its own bundle configuration under the alias &lt;code&gt;spryker_api_platform&lt;/code&gt;. It controls how YAML resource schemas are discovered across the &lt;code&gt;src/Spryker&lt;/code&gt;, &lt;code&gt;src/SprykerFeature&lt;/code&gt;, and &lt;code&gt;src/Pyz&lt;/code&gt; trees before they are handed to API Platform for code generation.&lt;/p&gt;
&lt;p&gt;The PHP configurator lives in a separate file per application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Glue:&lt;/strong&gt; &lt;code&gt;config/Glue/packages/spryker_api_platform.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GlueStorefront:&lt;/strong&gt; &lt;code&gt;config/GlueStorefront/packages/spryker_api_platform.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GlueBackend:&lt;/strong&gt; &lt;code&gt;config/GlueBackend/packages/spryker_api_platform.php&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;language-php 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;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;declare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strict_types&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Symfony\Config\SprykerApiPlatformConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;SprykerApiPlatformConfig&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;apiTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;storefront&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;configuration-options&quot;&gt;Configuration options&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Matches against&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apiTypes(array $types)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt; (all discovered)&lt;/td&gt;
&lt;td&gt;The list of API types (e.g., &lt;code&gt;storefront&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt;) this application exposes. Used both for schema directory lookup (&lt;code&gt;resources/api/{apiType}&lt;/code&gt;) and for filtering services annotated with &lt;code&gt;#[ApiType]&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sourceDirectories(array $directories)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[&apos;vendor/spryker&apos;, &apos;src/Pyz&apos;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Root directories scanned for &lt;code&gt;{Module}/resources/api/{apiType}/*.resource.{yaml,yml}&lt;/code&gt; schema files. Paths are resolved relative to the project root.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;includedPathFragments(array $fragments)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full real file path, &lt;code&gt;str_contains&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allowlist. When non-empty, only schema files whose real path contains at least one of the fragments are kept.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;excludedPathFragments(array $fragments)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full real file path, &lt;code&gt;str_contains&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Blocklist. Any schema file whose real path contains at least one fragment is dropped.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;includedModulePatterns(array $patterns)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Module directory name, &lt;code&gt;fnmatch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allowlist on the module name segment. When non-empty, only modules whose name matches at least one glob pattern contribute schemas.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;excludedModulePatterns(array $patterns)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Module directory name, &lt;code&gt;fnmatch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Blocklist on the module name segment. Modules whose name matches any pattern are skipped, even if included elsewhere.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;debug(bool $enabled)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%kernel.debug%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Disables caching and enables verbose output for the schema generator.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;evaluation-order&quot;&gt;Evaluation order&lt;/h3&gt;
&lt;p&gt;Filters are applied in the following order during schema discovery:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Module-level allowlist&lt;/strong&gt; (&lt;code&gt;includedModulePatterns&lt;/code&gt;). If set, a module must match at least one pattern or it is skipped entirely.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Module-level blocklist&lt;/strong&gt; (&lt;code&gt;excludedModulePatterns&lt;/code&gt;). Matching modules are skipped.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;File-level allowlist&lt;/strong&gt; (&lt;code&gt;includedPathFragments&lt;/code&gt;). If set, a schema file must match at least one fragment or it is skipped.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;File-level blocklist&lt;/strong&gt; (&lt;code&gt;excludedPathFragments&lt;/code&gt;). Matching files are skipped.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Blocklists always win over allowlists: a module or file that matches both the &lt;code&gt;included*&lt;/code&gt; and the &lt;code&gt;excluded*&lt;/code&gt; list is dropped.&lt;/p&gt;
&lt;h3 id=&quot;example-split-legacy-glue-and-api-platform-storefront-by-module-suffix&quot;&gt;Example: Split legacy Glue and API Platform storefront by module suffix&lt;/h3&gt;
&lt;p&gt;Projects that run the legacy Glue REST stack and the new API Platform storefront side by side typically want to route &lt;code&gt;*RestApi&lt;/code&gt; modules to the legacy app while the rest stays on API Platform. That split can be expressed declaratively:&lt;/p&gt;
&lt;div class=&quot;language-php 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;c1&quot;&gt;// config/Glue/packages/spryker_api_platform.php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;SprykerApiPlatformConfig&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;apiTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;storefront&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Legacy Glue app: only *RestApi modules.&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;includedModulePatterns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;*RestApi&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-php 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;c1&quot;&gt;// config/GlueStorefront/packages/spryker_api_platform.php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;SprykerApiPlatformConfig&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;apiTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;storefront&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// API Platform storefront: exclude every legacy *RestApi module.&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;excludedModulePatterns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;*RestApi&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;example-narrow-discovery-to-explicit-modules-or-paths&quot;&gt;Example: Narrow discovery to explicit modules or paths&lt;/h3&gt;
&lt;p&gt;When you want to opt in module-by-module, combine &lt;code&gt;includedPathFragments&lt;/code&gt; with precise path prefixes:&lt;/p&gt;
&lt;div class=&quot;language-php 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;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;includedPathFragments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;src/Pyz/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;src/Spryker/Cart/resources/api/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;src/Spryker/Customer/resources/api/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This allowlist keeps only schemas from project-level overrides plus two explicitly enabled core modules. Any schema file whose real path does not contain one of these fragments is skipped.&lt;/p&gt;
&lt;h3 id=&quot;example-per-resource-exclusion-on-a-module-you-otherwise-keep&quot;&gt;Example: Per-resource exclusion on a module you otherwise keep&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;excludedPathFragments&lt;/code&gt; remains useful for carve-outs that do not map to a whole module suffix — for example, when two applications each want to own a different &lt;code&gt;/token&lt;/code&gt; endpoint:&lt;/p&gt;
&lt;div class=&quot;language-php 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;c1&quot;&gt;// config/GlueStorefront/packages/spryker_api_platform.php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$sprykerApiPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;excludedPathFragments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;src/Spryker/AuthRestApi/resources/api/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This drops only the &lt;code&gt;AuthRestApi&lt;/code&gt; schemas while leaving the rest of the allowlist/blocklist logic untouched.&lt;/p&gt;
</description>
            <pubDate>Fri, 24 Apr 2026 12:53:30 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/architecture/api-platform/configuration.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/architecture/api-platform/configuration.html</guid>
            
            
        </item>
        
        <item>
            <title>API Platform</title>
            <description>&lt;p&gt;Spryker’s API Platform integration provides schema-based API resource generation with automatic OpenAPI documentation. This allows you to define your API resources using YAML schemas and automatically generate fully functional API endpoints with validation, pagination, and serialization.&lt;/p&gt;
&lt;p&gt;This document describes the API Platform architecture and how it integrates with Spryker.&lt;/p&gt;
&lt;h2 id=&quot;what-is-api-platform&quot;&gt;What is API Platform&lt;/h2&gt;
&lt;p&gt;API Platform is a framework for building modern APIs based on web standards and best practices. In Spryker, it complements the existing Glue API infrastructure by providing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Schema-based resource generation&lt;/strong&gt;: Define resources in YAML, generate PHP classes automatically&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic OpenAPI documentation&lt;/strong&gt;: Interactive API documentation generated from schemas&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in validation&lt;/strong&gt;: Symfony Validator integration with operation-specific rules&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pagination support&lt;/strong&gt;: Standardized pagination with configurable defaults&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State management&lt;/strong&gt;: Separate providers (read) and processors (write) for clean architecture&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Read more about the API Platform project at &lt;a href=&quot;https://api-platform.com/&quot;&gt;api-platform.com&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;architecture-overview&quot;&gt;Architecture overview&lt;/h2&gt;
&lt;h3 id=&quot;resource-generation-workflow&quot;&gt;Resource generation workflow&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-MARKDOWN&quot;&gt;&gt;Schema Files (YAML)
    ↓
Schema Discovery &amp;amp; Validation
    ↓
Multi-layer Schema Merging (Core → Feature → Project → [Code Buckets])
    ↓
Resource Class Generation
    ↓
API Platform Resource (with attributes)
    ↓
API Endpoints
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;core-components&quot;&gt;Core components&lt;/h3&gt;
&lt;h4 id=&quot;schema-files&quot;&gt;1. Schema files&lt;/h4&gt;
&lt;p&gt;Resources are defined in YAML files located in module directories:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-MARKDOWN&quot;&gt;&gt;src/Spryker/{Module}/resources/api/{api-type}/{resource-name}.resources.yml
src/Spryker/{Module}/resources/api/{api-type}/{resource-name}.validation.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example resource schema &lt;code&gt;src/Spryker/{Module}/resources/api/{api-type}/{resource-name}.resources.yml&lt;/code&gt;:&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;resource&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Customers&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;shortName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Customer&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Customer&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;API&quot;&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Pyz&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Glue&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Customer&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Api&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Backend&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Provider&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;CustomerBackendProvider&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;processor&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Pyz&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Glue&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Customer&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Api&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Backend&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Processor&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;CustomerBackendProcessor&quot;&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;paginationEnabled&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;operations&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Post&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Get&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;GetCollection&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Patch&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Delete&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;string&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Customer&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;address&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;customerReference&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;string&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;identifier&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;writable&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Example validation schema &lt;code&gt;src/Spryker/{Module}/resources/api/{api-type}/{resource-name}.validation.yml&lt;/code&gt;:&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;post&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;NotBlank&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;First name is required&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;min&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;max&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;64&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;minMessage&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;First name must be at least 2 characters&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;maxMessage&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;First name cannot exceed 64 characters&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;patch&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;constraints&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;min&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;max&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;64&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;minMessage&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;First name must be at least 2 characters&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;maxMessage&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;First name cannot exceed 64 characters&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;generated-resources&quot;&gt;2. Generated resources&lt;/h4&gt;
&lt;p&gt;The generator creates PHP classes with API Platform attributes:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/Generated/Api/Backend/CustomersBackendResource.php&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-php 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;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Generated\Api\Backend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ApiPlatform\Metadata\ApiResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ApiPlatform\Metadata\ApiProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Symfony\Component\Validator\Constraints&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;#[ApiResource(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;operations&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GetCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;shortName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Customer&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomerBackendProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;processor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomerBackendProcessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomersBackendResource&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#[ApiProperty(identifier: true, writable: false)]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;?string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$customerReference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;#[ApiProperty]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#[Assert\NotBlank(groups: [&apos;customers:create&apos;])]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#[Assert\Email(groups: [&apos;customers:create&apos;])]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;?string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Getters, setters, toArray(), fromArray()...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;state-providers-and-processors&quot;&gt;3. State providers and processors&lt;/h4&gt;
&lt;p&gt;Spryker ships abstract base classes (&lt;code&gt;AbstractBackendProvider&lt;/code&gt;, &lt;code&gt;AbstractStorefrontProvider&lt;/code&gt;, &lt;code&gt;AbstractBackendProcessor&lt;/code&gt;, &lt;code&gt;AbstractStorefrontProcessor&lt;/code&gt;) that dispatch operations automatically and expose request/context helpers. For details and examples, see &lt;a href=&quot;/docs/dg/dev/architecture/api-platform/state-providers-and-processors.html&quot;&gt;State providers and processors&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can also implement &lt;code&gt;ProviderInterface&lt;/code&gt; / &lt;code&gt;ProcessorInterface&lt;/code&gt; directly — see the API Platform public docs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://api-platform.com/docs/core/state-providers/&quot;&gt;API Platform Providers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api-platform.com/docs/core/state-processors/&quot;&gt;API Platform Processors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Provider (read operations):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-php 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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomerBackendProvider&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProviderInterface&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Operation&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uriVariables&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Fetch and return data from your business layer&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$customerResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Processor (write operations):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-php 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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomerBackendProcessor&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProcessorInterface&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;mixed&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Operation&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uriVariables&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;mixed&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Persist changes through your business layer&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$updatedResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;api-types&quot;&gt;API types&lt;/h2&gt;
&lt;p&gt;Any of the &lt;a href=&quot;https://docs.spryker.com/docs/integrations/spryker-glue-api/getting-started-with-apis/getting-started-with-apis&quot;&gt;existing APIs&lt;/a&gt; can be extended using API Platform.&lt;/p&gt;
&lt;p&gt;Spryker supports multiple API types for different use cases:&lt;/p&gt;
&lt;h3 id=&quot;glue-api&quot;&gt;Glue API&lt;/h3&gt;
&lt;p&gt;This API is configured to serve the JSON:API format by default, which can be configured per project. Projects migrating their APIs can provide new APIs as well as supporting the existing ones while migrating.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API Type:&lt;/strong&gt; &lt;code&gt;storefront&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application:&lt;/strong&gt; Glue&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Base URL:&lt;/strong&gt; &lt;code&gt;http://glue.eu.spryker.local/&lt;/code&gt; - Configurable per project&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; Customer-facing APIs, mobile apps, PWAs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;gluestorefront-api&quot;&gt;GlueStorefront API&lt;/h3&gt;
&lt;p&gt;Thie API is configured to serve the JSON+LD format by default, which can be configured per project.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API Type:&lt;/strong&gt; &lt;code&gt;storefront&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application:&lt;/strong&gt; Glue&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Base URL:&lt;/strong&gt; &lt;code&gt;http://glue-storefront.eu.spryker.local/&lt;/code&gt; - Configurable per project&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; Customer-facing APIs, mobile apps, PWAs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;gluebackend-api&quot;&gt;GlueBackend API&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API Type:&lt;/strong&gt; &lt;code&gt;backend&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application:&lt;/strong&gt; Zed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Base URL:&lt;/strong&gt; &lt;code&gt;http://glue-backend.eu.spryker.local/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; Admin panels, internal tools, ERP integrations&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;merchant-portal-api&quot;&gt;Merchant Portal API&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API Type:&lt;/strong&gt; &lt;code&gt;merchant-portal&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application:&lt;/strong&gt; MerchantPortal&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Base URL:&lt;/strong&gt; &lt;code&gt;http://mp.glue.eu.spryker.local/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; Marketplace merchant interfaces&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Example:&lt;/strong&gt; &lt;code&gt;/products&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;multi-layer-schema-merging&quot;&gt;Multi-layer schema merging&lt;/h2&gt;
&lt;p&gt;One of the key features is support for multi-layer schema definitions that automatically merge:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Core layer&lt;/strong&gt; (vendor/spryker):&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;resource&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Customers&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Feature layer&lt;/strong&gt; (src/SprykerFeature):&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;resource&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Customers&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;loyaltyPoints&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;integer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Project layer&lt;/strong&gt; (src/Pyz):&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;resource&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Customers&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;required&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;c1&quot;&gt;# Override core&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;customField&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;string&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Project-specific&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: A single merged resource with all properties, project code-bucket layer taking precedence.&lt;/p&gt;
&lt;h2 id=&quot;integration-with-spryker-architecture&quot;&gt;Integration with Spryker architecture&lt;/h2&gt;
&lt;h3 id=&quot;dependency-injection&quot;&gt;Dependency Injection&lt;/h3&gt;
&lt;p&gt;API Platform fully integrates with Symfony Dependency Injection:&lt;/p&gt;
&lt;div class=&quot;language-php 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;c1&quot;&gt;// config/Zed/ApplicationServices.php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$services&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Pyz\\Zed\\&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;../../../src/Pyz/Zed/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Providers and Processors are automatically discovered and can use constructor injection:&lt;/p&gt;
&lt;div class=&quot;language-php 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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomerBackofficeProvider&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProviderInterface&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CustomerFacadeInterface&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$customerFacade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CustomerRepositoryInterface&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$customerRepository&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;facade-integration&quot;&gt;Facade integration&lt;/h3&gt;
&lt;p&gt;Resources can leverage existing Spryker facades:&lt;/p&gt;
&lt;div class=&quot;language-php 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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomerBackendProcessor&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProcessorInterface&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CustomerFacadeInterface&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$customerFacade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;mixed&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Operation&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;mixed&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$customerTransfer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mapToTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customerFacade&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;createCustomer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$customerTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mapToResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getCustomerTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;resource-generation&quot;&gt;Resource generation&lt;/h2&gt;
&lt;h3 id=&quot;console-commands&quot;&gt;Console commands&lt;/h3&gt;
&lt;p&gt;All the following commands can be used with a specific GLUE_APPLICATION by prefixing them with &lt;code&gt;GLUE_APPLICATION=GLUE_BACKEND&lt;/code&gt; environment variable. For example: &lt;code&gt;docker/sdk cli GLUE_APPLICATION=GLUE_BACKEND glue api:debug --list&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash 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;c&quot;&gt;# Generate resource classes for all configured API types at once. Usually used during deployment/installation.&lt;/span&gt;
docker/sdk cli glue api:generate

&lt;span class=&quot;c&quot;&gt;# Generate API type specific resource classes. Usually used during development.&lt;/span&gt;
docker/sdk cli glue api:generate backend

&lt;span class=&quot;c&quot;&gt;# Validate schemas only to see if there is any issue in the definitions&lt;/span&gt;
docker/sdk cli glue api:generate &lt;span class=&quot;nt&quot;&gt;--validate-only&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;debug-commands&quot;&gt;Debug commands&lt;/h3&gt;
&lt;div class=&quot;language-bash 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;c&quot;&gt;# List all resources to see which ones are defined in the schema files.&lt;/span&gt;
docker/sdk cli glue  api:debug &lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Inspect specific resource and print details about properties and operations&lt;/span&gt;
docker/sdk cli glue  api:debug customers &lt;span class=&quot;nt&quot;&gt;--api-type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;backend

&lt;span class=&quot;c&quot;&gt;# Show merged schema&lt;/span&gt;
docker/sdk cli glue  api:debug customers &lt;span class=&quot;nt&quot;&gt;--api-type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;backend &lt;span class=&quot;nt&quot;&gt;--show-merged&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Show contributing files for a resource&lt;/span&gt;
docker/sdk cli glue  api:debug customers &lt;span class=&quot;nt&quot;&gt;--api-type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;backend &lt;span class=&quot;nt&quot;&gt;--show-sources&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;h3 id=&quot;automatic-openapi-documentation&quot;&gt;Automatic OpenAPI documentation&lt;/h3&gt;
&lt;p&gt;API Platform generates interactive OpenAPI documentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Swagger UI at the root URL &lt;code&gt;/&lt;/code&gt; for example &lt;code&gt;http://glue-backend.eu.spryker.local/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can disable this interface in production environments by configuring the settings in your &lt;code&gt;api_platform.php&lt;/code&gt; configuration file. For details, see &lt;a href=&quot;/docs/dg/dev/architecture/api-platform/configuration.html#disable-swaggerui-in-production&quot;&gt;Disable Swagger UI&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;built-in-validation&quot;&gt;Built-in validation&lt;/h3&gt;
&lt;p&gt;Validation rules from &lt;code&gt;*.validation.yml&lt;/code&gt; files are converted to Symfony Validator constraints:&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;post&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;NotBlank&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Email&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Becomes:&lt;/p&gt;
&lt;div class=&quot;language-php 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;c1&quot;&gt;#[Assert\NotBlank(groups: [&apos;customers:create&apos;])]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#[Assert\Email(groups: [&apos;customers:create&apos;])]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;?string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;pagination-support&quot;&gt;Pagination support&lt;/h3&gt;
&lt;p&gt;Standardized pagination with query parameters:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-MARKDOWN&quot;&gt;&gt;GET /customers?page=2&amp;amp;itemsPerPage=20
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Provider returns &lt;code&gt;PaginatorInterface&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-php 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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TraversablePaginator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ArrayObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$currentPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$itemsPerPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$totalItems&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;operation-specific-behavior&quot;&gt;Operation-specific behavior&lt;/h3&gt;
&lt;p&gt;Define different validation and behavior per operation:&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;operations&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Post&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# Create&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Get&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;# Read one&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;GetCollection&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# Read many&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Patch&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;# Update&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Delete&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# Delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Each operation can have specific validation rules and security settings.&lt;/p&gt;
&lt;h3 id=&quot;relationships&quot;&gt;Relationships&lt;/h3&gt;
&lt;p&gt;Include related resources via the &lt;code&gt;?include=&lt;/code&gt; query parameter:&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;includes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;relationshipName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;addresses&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;targetResource&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;CustomersAddresses&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;uriVariableMappings&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;customerReference&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;customerReference&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Request:&lt;/p&gt;
&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GET /customers/customer--35?include=addresses
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Response includes both the customer and related addresses in JSON:API format. No provider code changes required - relationships work automatically through decoration.&lt;/p&gt;
&lt;p&gt;For detailed information, see &lt;a href=&quot;/docs/dg/dev/architecture/api-platform/relationships.html&quot;&gt;Relationships&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;sparse-fieldsets&quot;&gt;Sparse fieldsets&lt;/h3&gt;
&lt;p&gt;Request only the attributes you need using the &lt;code&gt;fields&lt;/code&gt; query parameter:&lt;/p&gt;
&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GET /stores?fields[stores]=name,locale
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This returns only &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;locale&lt;/code&gt; in the response attributes, reducing payload size. Sparse fieldsets work with relationships too — filter attributes on both the main resource and included resources.&lt;/p&gt;
&lt;p&gt;For detailed information, see &lt;a href=&quot;/docs/dg/dev/architecture/api-platform/sparse-fieldsets.html&quot;&gt;Sparse Fieldsets&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;
&lt;h3 id=&quot;cache-warming&quot;&gt;Cache warming&lt;/h3&gt;
&lt;p&gt;Pre-generate resources during deployment:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker/sdk cli glue  api:generate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker/sdk cli glue  cache:warmup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;property-level-access-control&quot;&gt;Property-level access control&lt;/h3&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;properties&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;writable&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;c1&quot;&gt;# Can be written&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;readable&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Not in responses&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;comparison-with-glue-api&quot;&gt;Comparison with Glue API&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;API Platform&lt;/th&gt;
&lt;th&gt;Glue API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Definition&lt;/td&gt;
&lt;td&gt;Schema-based (YAML)&lt;/td&gt;
&lt;td&gt;Code-based (PHP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;td&gt;Auto-generated OpenAPI&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation&lt;/td&gt;
&lt;td&gt;Declarative&lt;/td&gt;
&lt;td&gt;Programmatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standards&lt;/td&gt;
&lt;td&gt;JSON-LD, Hydra&lt;/td&gt;
&lt;td&gt;JSON API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning curve&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Very high&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use cases&lt;/td&gt;
&lt;td&gt;Standard CRUD&lt;/td&gt;
&lt;td&gt;Complex business logic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Both can coexist in the same application. For further migration guidance, see &lt;a href=&quot;/docs/dg/dev/upgrade-and-migrate/migrate-to-api-platform.html&quot;&gt;How to migrate to API Platform&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;related-documentation&quot;&gt;Related documentation&lt;/h2&gt;
&lt;p&gt;For detailed implementation guides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/upgrade-and-migrate/integrate-api-platform.html&quot;&gt;How to integrate API Platform&lt;/a&gt; - Setup and configuration&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/upgrade-and-migrate/integrate-api-platform-security.html&quot;&gt;How to integrate API Platform Security&lt;/a&gt; - Authentication and authorization setup&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/upgrade-and-migrate/migrate-to-api-platform.html&quot;&gt;How to migrate to API Platform&lt;/a&gt; - Migrate endpoints from Glue API&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/configuration.html&quot;&gt;API Platform Configuration&lt;/a&gt; - Configure API Platform settings&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/security.html&quot;&gt;Security&lt;/a&gt; - Authentication and authorization&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/enablement.html&quot;&gt;API Platform Enablement&lt;/a&gt; - Creating your first resource&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/resource-schemas.html&quot;&gt;Resource Schemas&lt;/a&gt; - Resource Schemas&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/validation-schemas.html&quot;&gt;Validation Schemas&lt;/a&gt; - Validation Schemas&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/native-api-platform-resources.html&quot;&gt;Native API Platform Resources&lt;/a&gt; - Using native PHP attributes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/state-providers-and-processors.html&quot;&gt;State providers and processors&lt;/a&gt; - Abstract base classes for providers and processors&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/code-buckets.html&quot;&gt;CodeBucket Support&lt;/a&gt; - Region-specific resources&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/sparse-fieldsets.html&quot;&gt;Sparse Fieldsets&lt;/a&gt; - Request only needed attributes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/troubleshooting.html&quot;&gt;Troubleshooting API Platform&lt;/a&gt; - Common issues&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/upgrade-and-migrate/integrate-api-platform.html&quot;&gt;How to integrate API Platform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/upgrade-and-migrate/integrate-api-platform-security.html&quot;&gt;How to integrate API Platform Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/native-api-platform-resources.html&quot;&gt;Native API Platform Resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/architecture/api-platform/code-buckets.html&quot;&gt;CodeBucket Support in API Platform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api-platform.com/docs/&quot;&gt;API Platform official documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
            <pubDate>Fri, 24 Apr 2026 11:48:27 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/architecture/api-platform.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/architecture/api-platform.html</guid>
            
            
        </item>
        
        <item>
            <title>State providers and processors</title>
            <description>API Platform splits resource handling into two components:

- **Provider** — returns data for read operations (`Get`, `GetCollection`).
- **Processor** — mutates data for write operations (`Post`, `Patch`, `Delete`).

Spryker ships abstract base classes that handle operation dispatch, expose request/context helpers, and raise clear errors when a method is missing. Extend these instead of implementing `ProviderInterface` / `ProcessorInterface` directly.

## Class hierarchy

```MARKDOWN
AbstractProvider                 AbstractProcessor
├── AbstractBackendProvider      ├── AbstractBackendProcessor
└── AbstractStorefrontProvider   └── AbstractStorefrontProcessor
```

- Use **`AbstractBackend*`** for resources under the `GlueBackend` API (Zed admin context, user-scoped).
- Use **`AbstractStorefront*`** for resources under the `Glue` / `GlueStorefront` API (customer-scoped).
- Extend **`AbstractProvider`** / **`AbstractProcessor`** directly only when the resource is not tied to a backend or storefront context.

## Providers

`AbstractProvider` dispatches operations based on the incoming `Operation` type:

| Operation       | Method called       |
|-----------------|---------------------|
| `Get`           | `provideItem()`     |
| `GetCollection` | `provideCollection()` |
| `Post`          | returns `null` (the processor handles POST) |

Override only the methods you need. Unimplemented methods throw `BadMethodCallException` so missing handlers are caught early.

### Example: storefront provider

```php
&lt;?php

declare(strict_types=1);

namespace Pyz\Glue\Customer\Api\Storefront\Provider;

use Generated\Api\Storefront\CustomersStorefrontResource;
use Pyz\Glue\Customer\Business\CustomerFacadeInterface;
use Spryker\ApiPlatform\State\Provider\AbstractStorefrontProvider;

class CustomerStorefrontProvider extends AbstractStorefrontProvider
{
    public function __construct(
        private readonly CustomerFacadeInterface $customerFacade,
    ) {
    }

    protected function provideItem(): ?CustomersStorefrontResource
    {
        $customerReference = $this-&gt;getUriVariable(&apos;customerReference&apos;);
        $customerTransfer = $this-&gt;customerFacade-&gt;findCustomerByReference($customerReference);

        if ($customerTransfer === null) {
            return null;
        }

        return (new CustomersStorefrontResource())-&gt;fromArray($customerTransfer-&gt;toArray());
    }

    /**
     * @return array&lt;\Generated\Api\Storefront\CustomersStorefrontResource&gt;
     */
    protected function provideCollection(): array
    {
        $pagination = $this-&gt;getPagination();
        $collection = $this-&gt;customerFacade-&gt;getCustomerCollection($pagination);

        $resources = [];
        foreach ($collection-&gt;getCustomers() as $customerTransfer) {
            $resources[] = (new CustomersStorefrontResource())-&gt;fromArray($customerTransfer-&gt;toArray());
        }

        return $resources;
    }
}
```

## Processors

`AbstractProcessor` dispatches write operations to explicit methods:

| Operation | Method called     |
|-----------|-------------------|
| `Post`    | `processPost($data)` |
| `Patch`   | `processPatch($data)` |
| `Delete`  | `processDelete()` |

### Example: backend processor

```php
&lt;?php

declare(strict_types=1);

namespace Pyz\Glue\Customer\Api\Backend\Processor;

use Generated\Api\Backend\CustomersBackendResource;
use Generated\Shared\Transfer\CustomerTransfer;
use Pyz\Glue\Customer\Business\CustomerFacadeInterface;
use Spryker\ApiPlatform\State\Processor\AbstractBackendProcessor;

class CustomerBackendProcessor extends AbstractBackendProcessor
{
    public function __construct(
        private readonly CustomerFacadeInterface $customerFacade,
    ) {
    }

    protected function processPost(mixed $data): CustomersBackendResource
    {
        $customerTransfer = (new CustomerTransfer())-&gt;fromArray($data-&gt;toArray(), true);
        $customerTransfer = $this-&gt;customerFacade-&gt;createCustomer($customerTransfer)-&gt;getCustomerTransferOrFail();

        return (new CustomersBackendResource())-&gt;fromArray($customerTransfer-&gt;toArray());
    }

    protected function processPatch(mixed $data): CustomersBackendResource
    {
        $customerTransfer = (new CustomerTransfer())
            -&gt;fromArray($data-&gt;toArray(), true)
            -&gt;setCustomerReference($this-&gt;getUriVariable(&apos;customerReference&apos;));

        $customerTransfer = $this-&gt;customerFacade-&gt;updateCustomer($customerTransfer)-&gt;getCustomerTransferOrFail();

        return (new CustomersBackendResource())-&gt;fromArray($customerTransfer-&gt;toArray());
    }

    protected function processDelete(): null
    {
        $this-&gt;customerFacade-&gt;deleteCustomerByReference($this-&gt;getUriVariable(&apos;customerReference&apos;));

        return null;
    }
}
```

## Context helpers

Inside your provider or processor you have access to the active `Operation`, URI variables, and request-scoped data through protected helpers.

### Common helpers (available on all abstracts)

| Method                     | Description |
|----------------------------|-------------|
| `getOperation()`           | Current API Platform `Operation`. |
| `getUriVariables()`        | All URI variables of the current route. |
| `hasUriVariable($name)`    | Check whether a URI variable is set. |
| `getUriVariable($name)`    | Read a URI variable; throws `ApiPlatformContextException` if missing. |
| `hasRequest()` / `getRequest()` | Current Symfony `Request` from the context. |
| `hasLocale()` / `getLocale()`   | `LocaleTransfer` resolved by `AcceptLanguageLocaleSubscriber`. |
| `hasStore()` / `getStore()`     | `StoreTransfer` resolved from the request. |
| `getPagination()` *(provider only)* | `PaginationTransfer` built from the `page` and `perPage` query params (defaults: `1`, `10`). |

Always use the `has*()` guard before calling a `get*()` helper when the value may be absent — the `get*()` helper throws `ApiPlatformContextException` if the attribute is missing.

### Backend helpers

`AbstractBackendProvider` / `AbstractBackendProcessor` add:

| Method                   | Description |
|--------------------------|-------------|
| `hasUser()` / `getUser()` | `UserTransfer` of the authenticated Zed user. |

### Storefront helpers

`AbstractStorefrontProvider` / `AbstractStorefrontProcessor` add:

| Method                           | Description |
|----------------------------------|-------------|
| `hasCustomer()` / `getCustomer()` | `CustomerTransfer` of the authenticated customer. |
| `isGuestCustomer()`              | `true` when the customer is a guest. |
| `getCustomerReference()`         | Shortcut to `getCustomer()-&gt;getCustomerReferenceOrFail()`. |

## Pagination

`getPagination()` reads the standard query parameters and returns a fully populated `PaginationTransfer`. Pass it to your business layer and return the result as an array or a paginated collection:

```php
protected function provideCollection(): array
{
    $collection = $this-&gt;customerFacade-&gt;getCustomerCollection($this-&gt;getPagination());

    return array_map(
        fn ($customerTransfer) =&gt; (new CustomersBackendResource())-&gt;fromArray($customerTransfer-&gt;toArray()),
        $collection-&gt;getCustomers()-&gt;getArrayCopy(),
    );
}
```

Pagination response links (`first`, `last`, `prev`, `next`) are attached automatically by the API Platform integration.

## When to bypass the abstract classes

The abstract classes cover standard JSON:API CRUD. Implement `ProviderInterface` / `ProcessorInterface` directly when you need:

- Custom operation types or non-CRUD dispatch logic.
- Batch-loading across relationships — implement `BatchLoadableProviderInterface` instead.
- Full control over the `provide()` / `process()` signature (for example, returning `TraversablePaginator`).

## Related documentation

- [API Platform Enablement](/docs/dg/dev/architecture/api-platform/enablement.html)
- [Relationships](/docs/dg/dev/architecture/api-platform/relationships.html)
- [API Platform Providers](https://api-platform.com/docs/core/state-providers/)
- [API Platform Processors](https://api-platform.com/docs/core/state-processors/)
</description>
            <pubDate>Thu, 23 Apr 2026 10:50:56 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/architecture/api-platform/state-providers-and-processors.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/architecture/api-platform/state-providers-and-processors.html</guid>
            
            
        </item>
        
        <item>
            <title>Serializer</title>
            <description>The `spryker/serializer` module provides a thin Spryker service around the [Symfony Serializer component](https://symfony.com/doc/current/serializer.html). It exposes the four canonical operations — `serialize`, `deserialize`, `normalize`, `denormalize` — and accepts a `SerializerContextTransfer` instead of a raw context array, so projects get a typed, self-documenting API.

The companion `spryker/serializer-extension` module ships the plugin interfaces used to contribute custom normalizers and encoders.

## When to use it

Use the Serializer service when you need to:

- Convert objects or transfers to JSON, XML, CSV, or any other format supported by a registered encoder.
- Hydrate objects from raw input (strings or arrays) with consistent context handling.
- Plug custom (de)normalizers or (de)encoders into a shared, project-wide serializer instance.

For HTTP-facing serialization in API Platform resources, keep relying on API Platform&apos;s own serializer; the Spryker Serializer is meant for service-layer and plugin-level use cases.

## Public API

`Spryker\Service\Serializer\SerializerServiceInterface`

```php
public function serialize(mixed $data, string $format, ?SerializerContextTransfer $serializerContextTransfer = null): string;

public function deserialize(mixed $data, string $type, string $format, ?SerializerContextTransfer $serializerContextTransfer = null): mixed;

public function normalize(mixed $data, ?string $format = null, ?SerializerContextTransfer $serializerContextTransfer = null): array|string|int|float|bool|\ArrayObject|null;

public function denormalize(
    mixed $data,
    string $type,
    ?string $format = null,
    ?SerializerContextTransfer $serializerContextTransfer = null,
    ?object $objectToPopulate = null,
): mixed;
```

## Using the service

```php
use Generated\Shared\Transfer\SerializerContextTransfer;
use Spryker\Service\Serializer\SerializerServiceInterface;

class OrderExporter
{
    public function __construct(
        private readonly SerializerServiceInterface $serializerService,
    ) {
    }

    public function export(OrderTransfer $orderTransfer): string
    {
        $context = (new SerializerContextTransfer())
            -&gt;addGroup(&apos;export&apos;)
            -&gt;setIsSkipNullValues(true)
            -&gt;setDatetimeFormat(DATE_ATOM);

        return $this-&gt;serializerService-&gt;serialize($orderTransfer, &apos;json&apos;, $context);
    }
}
```

To hydrate a specific object instance instead of creating a new one, pass it as `objectToPopulate`:

```php
$order = new OrderTransfer();
$this-&gt;serializerService-&gt;denormalize($payload, OrderTransfer::class, &apos;json&apos;, null, $order);
```

## SerializerContextTransfer

The context transfer is the typed equivalent of the associative context array Symfony Serializer expects. It is mapped internally to the matching Symfony constants.

| Property                              | Maps to (Symfony)                                         |
|---------------------------------------|-----------------------------------------------------------|
| `groups`                              | `AbstractNormalizer::GROUPS`                              |
| `isSkipNullValues`                    | `AbstractObjectNormalizer::SKIP_NULL_VALUES`              |
| `isSkipUninitializedValues`           | `AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES`     |
| `isPreserveEmptyObjects`              | `AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS`        |
| `isEnableMaxDepth` / `maxDepth`       | `AbstractObjectNormalizer::ENABLE_MAX_DEPTH`              |
| `isAllowExtraAttributes`              | `AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES`              |
| `datetimeFormat` / `datetimeTimezone` | `DateTimeNormalizer::FORMAT_KEY` / `TIMEZONE_KEY`         |
| `isCollectDenormalizationErrors`      | `AbstractObjectNormalizer::COLLECT_DENORMALIZATION_ERRORS`|
| `isRequireAllProperties`              | `AbstractObjectNormalizer::REQUIRE_ALL_PROPERTIES`        |
| `isDisableTypeEnforcement`            | `AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT`      |
| `defaultConstructorArguments`         | `AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS`       |
| `symfonyContext`                      | Merged verbatim into the final context array              |

Any key that is not covered by a dedicated property can be supplied through `symfonyContext`, which is merged last.

## Extending the Serializer

Register custom (de)normalizers or (de)encoders through the plugin interfaces from `spryker/serializer-extension`.

### Normalizers

Implement `Spryker\Shared\SerializerExtension\Dependency\Plugin\SerializerNormalizerPluginInterface` and return one or more Symfony normalizer instances:

```php
&lt;?php

declare(strict_types=1);

namespace Pyz\Service\Serializer\Plugin;

use Spryker\Shared\SerializerExtension\Dependency\Plugin\SerializerNormalizerPluginInterface;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

class DefaultNormalizerPlugin implements SerializerNormalizerPluginInterface
{
    /**
     * @return array&lt;\Symfony\Component\Serializer\Normalizer\NormalizerInterface|\Symfony\Component\Serializer\Normalizer\DenormalizerInterface&gt;
     */
    public function getNormalizers(): array
    {
        return [
            new DateTimeNormalizer(),
            new ObjectNormalizer(),
        ];
    }
}
```

### Encoders

Implement `Spryker\Shared\SerializerExtension\Dependency\Plugin\SerializerEncoderPluginInterface`:

```php
&lt;?php

declare(strict_types=1);

namespace Pyz\Service\Serializer\Plugin;

use Spryker\Shared\SerializerExtension\Dependency\Plugin\SerializerEncoderPluginInterface;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;

class DefaultEncoderPlugin implements SerializerEncoderPluginInterface
{
    /**
     * @return array&lt;\Symfony\Component\Serializer\Encoder\EncoderInterface|\Symfony\Component\Serializer\Encoder\DecoderInterface&gt;
     */
    public function getEncoders(): array
    {
        return [
            new JsonEncoder(),
            new XmlEncoder(),
        ];
    }
}
```

### Wiring the plugins

Register your plugins in the project dependency provider:

`src/Pyz/Service/Serializer/SerializerDependencyProvider.php`

```php
&lt;?php

declare(strict_types=1);

namespace Pyz\Service\Serializer;

use Pyz\Service\Serializer\Plugin\DefaultEncoderPlugin;
use Pyz\Service\Serializer\Plugin\DefaultNormalizerPlugin;
use Spryker\Service\Serializer\SerializerDependencyProvider as SprykerSerializerDependencyProvider;

class SerializerDependencyProvider extends SprykerSerializerDependencyProvider
{
    /**
     * @return array&lt;\Spryker\Shared\SerializerExtension\Dependency\Plugin\SerializerNormalizerPluginInterface&gt;
     */
    protected function getSerializerNormalizerPlugins(): array
    {
        return [
            new DefaultNormalizerPlugin(),
        ];
    }

    /**
     * @return array&lt;\Spryker\Shared\SerializerExtension\Dependency\Plugin\SerializerEncoderPluginInterface&gt;
     */
    protected function getSerializerEncoderPlugins(): array
    {
        return [
            new DefaultEncoderPlugin(),
        ];
    }
}
```

Plugins are collected lazily; the underlying Symfony `Serializer` is built once on first use and reused for the life of the request.

## Installation

```bash
composer require spryker/serializer spryker/serializer-extension
```

## Related documentation

- [Symfony Serializer component](https://symfony.com/doc/current/serializer.html)
- [API Platform](/docs/dg/dev/architecture/api-platform.html)
</description>
            <pubDate>Thu, 23 Apr 2026 10:50:56 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/architecture/serializer.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/architecture/serializer.html</guid>
            
            
        </item>
        
        <item>
            <title>AI Dev SDK Overview</title>
            <description>&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;Experimental module&lt;/div&gt;
&lt;p&gt;The AiDev module is experimental and not stable. There is no backward compatibility promise for this module. We welcome your feedback and contributions as we continue to develop and improve this module.&lt;/p&gt;
&lt;/div&gt;&lt;/section&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;Prerequisites&lt;/div&gt;
&lt;p&gt;This module requires &lt;code&gt;^1.71.0&lt;/code&gt; version of &lt;code&gt;docker/sdk&lt;/code&gt; for proper usage.
Make sure your development environment is up to date before installing the AiDev module.&lt;/p&gt;
&lt;/div&gt;&lt;/section&gt;
&lt;p&gt;This document describes how to integrate and use the AiDev module to connect your Spryker application to AI development tools through the Model Context Protocol (MCP).&lt;/p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;The AiDev module provides an MCP server that enables AI assistants to interact with your Spryker application.
It exposes Spryker-specific information through MCP tools and prompts, allowing AI assistants to better understand and work with your codebase.&lt;/p&gt;
&lt;p&gt;The module includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MCP Server&lt;/strong&gt;: A console command that runs an MCP server to communicate with AI assistants&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extension Points&lt;/strong&gt;: Plugin interfaces for adding custom MCP tools and prompts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in Tools&lt;/strong&gt;: Pre-configured tools for accessing Spryker transfers, interfaces, and OMS information&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prompt Generation&lt;/strong&gt;: Automatic generation of context-aware prompts from documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;console-commands&quot;&gt;Console commands&lt;/h2&gt;
&lt;p&gt;The AiDev module provides the following console commands:&lt;/p&gt;
&lt;h3 id=&quot;mcp-server-command&quot;&gt;MCP Server Command&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ai-dev:mcp-server&lt;/code&gt; command starts an MCP server that allows AI assistants to interact with your Spryker application.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker/sdk console ai-dev:mcp-server &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This command:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Starts an MCP server using stdio transport&lt;/li&gt;
&lt;li&gt;Registers all configured MCP tool and prompt plugins&lt;/li&gt;
&lt;li&gt;Automatically generates prompts if they don’t exist&lt;/li&gt;
&lt;li&gt;Listens for requests from AI assistants&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;: This command is typically configured in AI assistant tools (like Claude Desktop) to enable them to access Spryker-specific information.&lt;/p&gt;
&lt;h3 id=&quot;setup-command&quot;&gt;Setup Command&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ai-dev:setup&lt;/code&gt; command sets up AI tooling for your Spryker project. It generates rules, an agents/context file, and skills — all tailored to the selected AI tool.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker/sdk console ai-dev:setup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The command automatically detects the AI tool installed in your project and prompts you to confirm or select a different one. It then generates the following for the selected tool:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rules&lt;/strong&gt;: Coding conventions and architectural guidelines.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agents/context file&lt;/strong&gt;: Project-specific context for AI agents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skills&lt;/strong&gt;: Reusable task-specific AI skill files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Output modes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The command supports two output modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ready to use&lt;/strong&gt;: Files are generated directly in the tool-specific directories listed in the table below.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Example&lt;/strong&gt;: Files are generated in example directories — for example, &lt;code&gt;.claude/rules-example/&lt;/code&gt; instead of &lt;code&gt;.claude/rules/&lt;/code&gt;. Rename the directories when ready to use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Output locations by AI tool&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;AI tool&lt;/th&gt;
&lt;th&gt;Rules directory&lt;/th&gt;
&lt;th&gt;Agents/context file&lt;/th&gt;
&lt;th&gt;Skills directory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.claude/rules/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.claude/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windsurf&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.windsurf/rules/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.windsurfrules&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.windsurf/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/instructions/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.cursor/rules/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.cursor/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenCode&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.opencode/rules/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.agents/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codex CLI&lt;/td&gt;
&lt;td&gt;Not supported — see below&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.agents/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Codex CLI does not have a native rules format. When you select it, the command offers to generate rules in another tool’s format instead and places them in that tool’s rules directory.&lt;/p&gt;
&lt;section class=&apos;info-block &apos;&gt;&lt;i class=&apos;info-block__icon icon-info&apos;&gt;&lt;/i&gt;&lt;div class=&apos;info-block__content&apos;&gt;&lt;div class=&quot;info-block__title&quot;&gt;GitHub Copilot and Docker sync&lt;/div&gt;
&lt;p&gt;If you use Docker sync, the &lt;code&gt;/.git*&lt;/code&gt; entry in &lt;code&gt;.dockersyncignore&lt;/code&gt; also excludes the &lt;code&gt;.github&lt;/code&gt; folder, which prevents Copilot-generated files from being available inside the container. To fix this, add the following line to &lt;code&gt;.dockersyncignore&lt;/code&gt; after the &lt;code&gt;/.git*&lt;/code&gt; entry:&lt;/p&gt;
&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;!/.github
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/section&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;: Run this command once when setting up AI tooling for a project.&lt;/p&gt;
&lt;h3 id=&quot;generate-prompts-command&quot;&gt;Generate Prompts Command&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ai-dev:generate-prompts&lt;/code&gt; command generates MCP prompts from a configured &lt;a href=&quot;https://github.com/spryker-dev/prompt-library&quot;&gt;Prompt Library&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker/sdk console ai-dev:generate-prompts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This command:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fetches prompts&lt;/li&gt;
&lt;li&gt;Generates PHP-based prompt classes&lt;/li&gt;
&lt;li&gt;Stores generated prompts in the configured directory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;: Use this command when you need to regenerate prompts from updated documentation or when initializing the module for the first time.&lt;/p&gt;
&lt;h2 id=&quot;extension-points&quot;&gt;Extension points&lt;/h2&gt;
&lt;p&gt;The AiDev module provides plugin interfaces for extending the MCP server with custom functionality:&lt;/p&gt;
&lt;h3 id=&quot;aidevmcptoolplugininterface&quot;&gt;AiDevMcpToolPluginInterface&lt;/h3&gt;
&lt;p&gt;Implement this interface to add custom MCP tools that AI assistants can use to query or interact with your application.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Interface location&lt;/strong&gt;: &lt;code&gt;SprykerSdk\Zed\AiDev\Dependency\AiDevMcpToolPluginInterface&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integration&lt;/strong&gt;: Register your tool plugins in &lt;code&gt;AiDevDependencyProvider::getMcpToolPlugins()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-php 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;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Pyz\Zed\AiDev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerSdk\Zed\AiDev\AiDevDependencyProvider&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerAiDevDependencyProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pyz\Zed\AiDev\Communication\Plugins\CustomAiDevMcpToolPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AiDevDependencyProvider&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerAiDevDependencyProvider&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/**
     * @return array&amp;lt;\SprykerSdk\Zed\AiDev\Dependency\AiDevMcpToolPluginInterface&amp;gt;
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getMcpToolPlugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;array_merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getMcpToolPlugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomAiDevMcpToolPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;aidevmcppromptplugininterface&quot;&gt;AiDevMcpPromptPluginInterface&lt;/h3&gt;
&lt;p&gt;Implement this interface to add custom MCP prompts that provide context or instructions to AI assistants.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Interface location&lt;/strong&gt;: &lt;code&gt;SprykerSdk\Zed\AiDev\Dependency\AiDevMcpPromptPluginInterface&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integration&lt;/strong&gt;: Register your prompt plugins in &lt;code&gt;AiDevDependencyProvider::getMcpPromptPlugins()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-php 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;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Pyz\Zed\AiDev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerSdk\Zed\AiDev\AiDevDependencyProvider&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerAiDevDependencyProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pyz\Zed\AiDev\Communication\Plugins\CustomAiDevMcpPromptPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AiDevDependencyProvider&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerAiDevDependencyProvider&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/**
     * @return array&amp;lt;\SprykerSdk\Zed\AiDev\Dependency\AiDevMcpPromptPluginInterface&amp;gt;
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getMcpPromptPlugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomAiDevMcpPromptPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The AiDev module can be configured through the &lt;code&gt;AiDevConfig&lt;/code&gt; class. Key configuration options include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prompt Directory&lt;/strong&gt;: Set the directory where generated prompts are stored&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Refer to the module’s configuration class for available options and their default values.&lt;/p&gt;
&lt;h2 id=&quot;debugging-the-mcp-server&quot;&gt;Debugging the MCP server&lt;/h2&gt;
&lt;p&gt;Before connecting your MCP server to AI assistants, you can test and debug it using the &lt;a href=&quot;https://modelcontextprotocol.io/docs/tools/inspector&quot;&gt;MCP Inspector&lt;/a&gt; tool. The inspector provides a web interface to interact with your MCP server, test tools, and verify that everything works correctly.&lt;/p&gt;
&lt;h3 id=&quot;using-the-mcp-inspector&quot;&gt;Using the MCP Inspector&lt;/h3&gt;
&lt;p&gt;Navigate to your Spryker project directory and run:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npx @modelcontextprotocol/inspector docker/sdk console ai-dev:mcp-server &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This command will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start the MCP Inspector in your browser&lt;/li&gt;
&lt;li&gt;Connect to your local MCP server&lt;/li&gt;
&lt;li&gt;Display all available tools and prompts&lt;/li&gt;
&lt;li&gt;Allow you to test tool calls interactively&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With Xdebug&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npx @modelcontextprotocol/inspector docker/sdk cli &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; console ai-dev:mcp-server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;section class=&apos;info-block &apos;&gt;&lt;i class=&apos;info-block__icon icon-info&apos;&gt;&lt;/i&gt;&lt;div class=&apos;info-block__content&apos;&gt;&lt;div class=&quot;info-block__title&quot;&gt;Node.js required&lt;/div&gt;
&lt;p&gt;The MCP Inspector requires Node.js to be installed on your system. The &lt;code&gt;npx&lt;/code&gt; command will automatically download and run the inspector tool without requiring a global installation.&lt;/p&gt;
&lt;/div&gt;&lt;/section&gt;
&lt;p&gt;&lt;img src=&quot;https://spryker.s3.eu-central-1.amazonaws.com/docs/dg/dev/ai-dev/mcp-inspector.png&quot; alt=&quot;MCP Inspector&quot; /&gt;&lt;/p&gt;
</description>
            <pubDate>Thu, 23 Apr 2026 07:22:30 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/ai/ai-dev/ai-dev-overview.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/ai/ai-dev/ai-dev-overview.html</guid>
            
            
        </item>
        
        <item>
            <title>AI Dev SDK</title>
            <description>&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;Warning&lt;/div&gt;
&lt;p&gt;Before you use AI-related tools, consult your legal department.&lt;/p&gt;
&lt;/div&gt;&lt;/section&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;When you use AI tools to write code, they rely on general patterns, which leads to mistakes and requires you to repeatedly explain your project structure.&lt;/p&gt;
&lt;p&gt;The AI Dev SDK provides an MCP server, which is a console command that your AI tool runs in your project’s Docker container and helps it to increase Spryker-context awareness. MCP (Model Context Protocol) is a standard protocol that lets AI tools request specific information from external sources, similar to how a browser requests data from an API.&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;After you install the SDK, &lt;a href=&quot;/docs/dg/dev/ai/ai-dev/ai-dev-mcp-server.html&quot;&gt;add a simple configuration&lt;/a&gt; to your AI tool. When your Spryker project is running, your AI tool can access Spryker-specific information and prompts through the MCP server.&lt;/p&gt;
&lt;h2 id=&quot;result&quot;&gt;Result&lt;/h2&gt;
&lt;p&gt;AI generates better code faster and with fewer errors. You spend less time correcting mistakes and explaining Spryker concepts.&lt;/p&gt;
&lt;h2 id=&quot;key-capabilities&quot;&gt;Key capabilities&lt;/h2&gt;
&lt;h3 id=&quot;faster-spryker-specific-answers&quot;&gt;Faster Spryker-specific answers&lt;/h3&gt;
&lt;p&gt;AI can search Spryker documentation instead of requiring you to explain basic concepts or guessing how features work.&lt;/p&gt;
&lt;h3 id=&quot;smarter-code-generation&quot;&gt;Smarter code generation&lt;/h3&gt;
&lt;p&gt;AI can look up your actual transfer objects, module dependencies, and interface methods so that the generated code matches your project structure instead of relying on assumptions.&lt;/p&gt;
&lt;h3 id=&quot;oms-debugging-made-easy&quot;&gt;OMS debugging made easy&lt;/h3&gt;
&lt;p&gt;AI can analyze your OMS flows to find possible next states, transitions, conditions, and timeouts for any order or state. This capability is especially helpful when you work with complex OMS schemas. You no longer need to manually follow arrows in large diagrams.&lt;/p&gt;
&lt;h3 id=&quot;working-with-complex-data-imports&quot;&gt;Working with complex data imports&lt;/h3&gt;
&lt;p&gt;AI can analyze, modify, and transform multi-column CSV files correctly. This task normally requires significant manual effort.&lt;/p&gt;
&lt;h3 id=&quot;sharing-prompts-across-your-team&quot;&gt;Sharing prompts across your team&lt;/h3&gt;
&lt;p&gt;The SDK includes access to the Spryker prompt library, and you can add your own project-specific prompts. This means your team can reuse effective prompts instead of everyone writing their own.&lt;/p&gt;
&lt;h3 id=&quot;database-queries&quot;&gt;Database queries&lt;/h3&gt;
&lt;p&gt;AI can execute read-only database queries to inspect data when debugging issues.&lt;/p&gt;
&lt;h3 id=&quot;extensible-for-your-project&quot;&gt;Extensible for your project&lt;/h3&gt;
&lt;p&gt;You can extend the MCP server by creating custom plugins (to add new tools) and custom prompts.&lt;/p&gt;
&lt;h2 id=&quot;install-the-ai-dev-sdk&quot;&gt;Install the AI Dev SDK&lt;/h2&gt;
&lt;h3 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h3&gt;
&lt;p&gt;Ensure that you have a Spryker project with Composer installed.&lt;/p&gt;
&lt;h3 id=&quot;installation-steps&quot;&gt;Installation steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Require the package as a development dependency:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;composer require spryker-sdk/ai-dev &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate the transfer objects:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;console transfer:generate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Register the console commands in your &lt;code&gt;ConsoleDependencyProvider&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-php 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;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerSdk\Zed\AiDev\Communication\Console\AiToolSetupConsole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerSdk\Zed\AiDev\Communication\Console\GeneratePromptsConsole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SprykerSdk\Zed\AiDev\Communication\Console\McpServerConsole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getConsoleCommands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Container&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;class_exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;McpServerConsole&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;McpServerConsole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;class_exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GenerateSkillsConsole&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AiToolSetupConsole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;class_exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GeneratePromptsConsole&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GeneratePromptsConsole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Connect the AI Dev SDK to your AI agent. For detailed configuration instructions, see &lt;a href=&quot;/docs/dg/dev/ai/ai-dev/ai-dev-mcp-server.html&quot;&gt;Configure the AiDev MCP server&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/ai/ai-dev/ai-dev-mcp-server.html&quot;&gt;Configure the AiDev MCP server&lt;/a&gt; - Set up the connection to your AI tool&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dg/dev/ai/ai-dev/ai-dev-overview.html&quot;&gt;AI Dev SDK Overview&lt;/a&gt; - Learn more about the AI Dev SDK features and capabilities&lt;/li&gt;
&lt;/ul&gt;
</description>
            <pubDate>Thu, 23 Apr 2026 07:15:42 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/ai/ai-dev/ai-dev.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/ai/ai-dev/ai-dev.html</guid>
            
            
        </item>
        
        <item>
            <title>Test console commands</title>
            <description>Spryker supports several [test helpers](/docs/dg/dev/guidelines/testing-guidelines/test-helpers/test-helpers.html) to assist you in testing your project. This article provides details of how to test console commands with ConsoleHelper.

To test console commands, do the following:

1. Add `\SprykerTest\Zed\Console\Helper\ConsoleHelper` to the `codeception.yml` file:

```yml
suites:
    Communication:
        path: Communication
        actor: {ModuleName}CommunnicationTester
        modules:
            enabled:
                - \SprykerTest\Zed\Console\Helper\ConsoleHelper
                - ...
```

For more information about the `codeception.yml` file, see [Test framework](/docs/dg/dev/guidelines/testing-guidelines/test-framework.html).

2. Create the test directory `tests/PyzTests/Zed/FooModule/Communication/Plugin/Console/`, if it&apos;s not available yet.
3. Add the test class:

```php
&lt;?php

namespace PyzTest\Zed\FooModule\Communication\Plugin\Console;

use Codeception\Test\Unit;
use PyzTest\Zed\FooModule\FooModuleCommunicationTester;

class MyConsoleCommandTest extends Unit
{
    /**
     * @var \{Organization}Test\Zed\FooModule\FooModuleCommunicationTester
     */
    protected FooModuleCommunicationTester $tester;
}
```

4. Add the test method:

```php
public function testMyConsoleCommand(): void
{
    // You can also use a mocked command or add a mocked facade etc.
    $command = new MyConsoleCommand();
    $commandTester = $this-&gt;tester-&gt;getConsoleTester($command);

    $input = [
        MyConsoleCommand::ARGUMENT_FOO =&gt; &apos;foo-argument&apos;,
        &apos;--&apos; . MyConsoleCommand::OPTION_BAR =&gt; &apos;bar-option&apos;,
    ];

    $commandTester-&gt;execute($input);

    $this-&gt;assertSame(MyConsoleCommand::CODE_SUCCESS, $commandTester-&gt;getStatusCode());

    // When you expect some output from the console command you can assert it with:
    $this-&gt;assertStringContainsString(&apos;My console command output.&apos;, $commandTester-&gt;getDisplay());
}
```

That&apos;s it. You are all set to test the console commands.
</description>
            <pubDate>Wed, 22 Apr 2026 12:15:12 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/guidelines/testing-guidelines/executing-tests/test-console-commands.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/guidelines/testing-guidelines/executing-tests/test-console-commands.html</guid>
            
            
        </item>
        
        <item>
            <title>New Relic transactions grouping by queue names</title>
            <description>By default, the `spryker/monitoring` module groups all New Relic transactions generated from a console command by the command&apos;s name. For example, `ooms:check-timeout`.

This strategy works in most cases, and you can still query the data from a needed queue using [NRQL](https://docs.newrelic.com/docs/query-your-data/nrql-new-relic-query-language/get-started/nrql-syntax-clauses-functions/). But you might want to override this behavior.

For example, you run  multiple commands like `queue:task:start publish.product_abstract` and `queue:task:start sync.storage.url`. With the default naming strategy, all the calls of the command will be grouped together by `queue:task:start`. Transaction data is aggregated under the same name for all types of queue processors.

In New Relic dashboard, this looks as follows:

![Transactions under the same name](https://spryker.s3.eu-central-1.amazonaws.com/docs/scos/dev/guidelines/performance-guidelines/elastic-computing/enable-queue-task-flow-in-new-relic.md/transactions-under-the-same-name.png)

## Group transactions by queue name

As queue name usually comes as the first argument of a command, to enable grouping by names, you need to need to enable grouping by the first argument as follows:

1. Integrate the `spryker/monitoring` module.
2. Provide an advanced extendable infrastructure for [New relic monitoring transaction](https://docs.newrelic.com/docs/apm/transactions/intro-transactions/transactions-new-relic-apm/) naming strategies. This lets you implement, configure, and override the default transaction naming behavior.
3. Implement the strategy that enables configured console commands to apply naming that groups transaction by command name and first argument.
4. Enable the new strategy for `queue:task:start` on the project level.

As a result, the transactions are displayed as follows:

![Aggregation of transactions](https://spryker.s3.eu-central-1.amazonaws.com/docs/scos/dev/guidelines/performance-guidelines/elastic-computing/enable-queue-task-flow-in-new-relic.md/aggregation-of-transactions.png)

## Integrate New Relic transactions grouping by queue names

For instructions, see [Integrate New Relic transactions grouping by queue names](/docs/dg/dev/integrate-and-configure/integrate-elastic-computing.html#integrate-new-relic-monitoring).

## Implementation details

![New Relic transaction grouping by name implementation details](https://confluence-connect.gliffy.net/embed/image/59eaf32b-df1e-4fb9-a5e7-64b77c8ab870.png?utm_medium=live&amp;utm_source=custom)
</description>
            <pubDate>Wed, 22 Apr 2026 12:15:12 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/guidelines/performance-guidelines/elastic-computing/new-relic-transaction-grouping-by-queue-names.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/guidelines/performance-guidelines/elastic-computing/new-relic-transaction-grouping-by-queue-names.html</guid>
            
            
        </item>
        
        <item>
            <title>E2E Testing with Cypress</title>
            <description>&lt;p&gt;Cypress is an end-to-end testing framework that provides a modern approach to testing web applications. Spryker provides a Cypress boilerplate project with pre-configured setup, best practices, and examples for testing Spryker-based applications.&lt;/p&gt;
&lt;h2 id=&quot;cypress-boilerplate&quot;&gt;Cypress boilerplate&lt;/h2&gt;
&lt;p&gt;For comprehensive information on setting up and using Cypress with Spryker, refer to the &lt;a href=&quot;https://github.com/spryker-projects/cypress-boilerplate&quot;&gt;cypress-boilerplate&lt;/a&gt; repository.&lt;/p&gt;
&lt;p&gt;The boilerplate includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pre-configured Cypress setup optimized for Spryker projects&lt;/li&gt;
&lt;li&gt;Example test cases and patterns&lt;/li&gt;
&lt;li&gt;Documentation and best practices&lt;/li&gt;
&lt;li&gt;Integration guides&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The boilerplate does NOT include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete test coverage - you should add and adjust example tests to fit your project&lt;/li&gt;
&lt;li&gt;Correct locators - the locators in the boilerplace are based on Spryker demo shops, adjust the locators in accordance with your project&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;internal-cypress-tests&quot;&gt;Internal Cypress tests&lt;/h2&gt;
&lt;p&gt;Cypress tests are used by Spryker for internal testing of the core Spryker features as well. You should remove the mentions of &lt;code&gt;cypress-tests&lt;/code&gt; from &lt;code&gt;composer.json&lt;/code&gt;. You can re-use and customize these tests for your project, however, Spryker does not guarantee these tests will work on your project, if you keep them. Spryker recommends you use the &lt;a href=&quot;https://github.com/spryker-projects/cypress-boilerplate/wiki&quot;&gt;boilerplate&lt;/a&gt; instead.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Repository&lt;/strong&gt;: &lt;a href=&quot;https://github.com/spryker-projects/cypress-boilerplate&quot;&gt;spryker-projects/cypress-boilerplate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wiki&lt;/strong&gt;: &lt;a href=&quot;https://github.com/spryker-projects/cypress-boilerplate/wiki&quot;&gt;cypress-boilerplate Wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
            <pubDate>Wed, 22 Apr 2026 12:15:12 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/guidelines/testing-guidelines/cypress-testing.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/guidelines/testing-guidelines/cypress-testing.html</guid>
            
            
        </item>
        
    </channel>
</rss>
