spryker / api-platform
ApiPlatform module
Requires
- php: >=8.3
- api-platform/api-pack: ^1.4.0
- api-platform/doctrine-common: ^4.3.0
- api-platform/doctrine-orm: ^4.3.0
- api-platform/documentation: ^4.3.0
- api-platform/hal: ^4.3.0
- api-platform/http-cache: ^4.3.0
- api-platform/hydra: ^4.3.0
- api-platform/json-api: ^4.3.0
- api-platform/json-schema: ^4.3.0
- api-platform/jsonld: ^4.3.0
- api-platform/metadata: ^4.3.0
- api-platform/openapi: ^4.3.0
- api-platform/serializer: ^4.3.0
- api-platform/state: ^4.3.0
- api-platform/symfony: ^4.3.0
- api-platform/validator: ^4.3.0
- friendsofcxml/cxml-php: ^2.0.0
- spryker/doctrine-inflector: ^1.0.0 || ^2.0.0
- spryker/entity-tag: ^1.0.0
- spryker/glossary-storage: ^1.0.0
- spryker/kernel: ^3.48.0
- spryker/locale: ^4.0.0
- spryker/log: ^3.0.0
- spryker/oauth: ^2.0.0
- spryker/store: ^1.0.0
- spryker/transfer: ^3.27.0
- symfony/config: ^6.0.0 || ^7.0.0
- symfony/console: ^6.0.0 || ^7.0.0
- symfony/expression-language: ^6.0.0 || ^7.0.0
- symfony/finder: ^6.0.0 || ^7.0.0
- symfony/http-kernel: ^6.0.0 || ^7.0.0
- symfony/security-bundle: ^6.0.0 || ^7.0.0
- symfony/yaml: ^6.0.0 || ^7.0.0
Requires (Dev)
Conflicts
- spryker/serializer: <1.1.0
This package is auto-updated.
Last update: 2026-07-21 07:07:07 UTC
README
Installation
composer require spryker/api-platform
Canonical nested objects (*.object.yml)
A project can define the canonical inner shape of a nested object once and have it flow into every resource that tags the matching objectName. With no object files present the generator output is byte-for-byte identical to the default behavior — it is a pure project opt-in.
File location
Canonical object files live in a dedicated, reserved subdirectory literally named objects/ — distinct from resource definition files. The directory name is always objects, never named after a resource or module.
To contrast the two kinds of files clearly:
resources/api/storefront/
├── checkout.resource.yml # a resource definition
├── checkout.validation.yml # its validation
└── objects/ # reserved dir — canonical objects only
├── address.object.yml
└── address.object.validation.yml
Only *.object.yml and *.object.validation.yml files belong in objects/. Resource files (*.resource.yml) are placed directly in the per-apiType directory, never inside objects/.
Naming The <dashed-name>.<kind>.yml pattern is shared by both file types — only the kind word differs. address.object.yml is the canonical-object analog of checkout.resource.yml; address.object.validation.yml is the analog of checkout.validation.yml. The object vs resource distinction marks the artifact kind, not a different naming scheme.
Full path patterns:
resources/api/<apiType>/objects/<dashed-name>.object.yml
resources/api/<apiType>/objects/<dashed-name>.object.validation.yml # optional validation
Example paths:
src/Pyz/resources/api/storefront/objects/address.object.ymlsrc/Pyz/resources/api/storefront/objects/address.object.validation.yml
Central directory
A project may also keep canonical object files in one central, configured location instead of (or in addition to) the per-module objects/ directories. Both locations are scanned and supported simultaneously.
Enable it via the Symfony bundle config node spryker_api_platform.canonical_object_search_directories, keyed by API type. Relative paths are resolved against the project root; %kernel.project_dir% is also supported:
# config/packages/spryker_api_platform.yaml spryker_api_platform: canonical_object_search_directories: storefront: - '%kernel.project_dir%/config/api/objects/storefront'
config/api/objects/<apiType>/<dashed-name>.object.yml
config/api/objects/<apiType>/<dashed-name>.object.validation.yml # optional validation
The same *.object.yml / *.object.validation.yml filename rules apply. The core default is an empty list, so without this configuration behavior is identical to scanning module locations only. Files in a central directory are always treated as the project layer (their path carries no /Pyz/ segment for path-based detection), so they participate in the standard project > feature > core precedence.
Defining the same objectName more than once within the same layer (for example one module file and one central-directory file, both project) is a fail-loud error: generation aborts with an ApiSchemaGenerationException naming both source files. The same name across different layers is fine — that is the normal override.
File format
# address.object.yml object: name: Address # CamelCase; matches objectName: Address in resource YAMLs properties: salutation: { type: string, description: 'Address salutation.' } firstName: { type: string, description: 'First name.' } zipCode: { type: string, description: 'ZIP / postal code.' }
| Key | Type | Required | Notes |
|---|---|---|---|
object.name |
string | yes | CamelCase; must match the objectName: join tag in resource YAMLs |
object.properties |
map | yes | Field definitions — same syntax as resource properties |
object.extends |
string | no | CamelCase name of another canonical object; its resolved fields are inherited first |
object.omit |
string[] | no | Field names to drop from the extends base before applying own properties |
Composition (extends / omit)
# address-snapshot.object.yml object: name: AddressSnapshot extends: Address # inherits all Address fields omit: [id, idCompanyBusinessUnitAddress] # drops write-only fields properties: country: { type: string, description: 'Country name.' } # adds read-only field
Resolution order: base extends fields → omit removals → own properties (own wins). Cycles throw ApiSchemaGenerationException.
objectName join tag
Every resource property that declares objectName: Address is the join key for this feature:
# checkout.resource.yml (core — ships dormant tags) properties: billingAddress: type: object objectName: Address # dormant when no address.object.yml exists; activates when the file is present readable: false writable: true properties: zipCode: { type: string }
When a canonical file for Address exists:
- The property's inner
propertiesare replaced with the canonical shape. - The mount attributes (
readable,writable,required,nullable) stay on the reference site — they are not owned by the canonical. - One shared
Generated\Api\<ApiType>\Addressclass is emitted; no per-resource companion class is generated for that property.
When no canonical file exists, the inline properties block is used exactly as today (no change).
Validation
Field-level validation is authored in the parallel *.object.validation.yml using the same format as resource validation files. On a canonicalized property the reference site's own Collection constraint is superseded by an Assert\Valid cascade to the canonical class, which carries the field-level constraints.
Layer precedence
Layer detection uses the same path rules as resource files: /Pyz/ → project, /SprykerFeature/ → feature, else core. Merge precedence: project > feature > core — so a project can add one field to a feature-layer canonical without redefining the whole object.
Core ships no *.object.yml files. The feature is available for project, feature, and core layers; today only projects use it.
Generated output
One shared class per canonical object is emitted to Generated\Api\<ApiType>\<ObjectName> (e.g. Generated\Api\Storefront\Address). All resource classes that reference the canonical use this single shared class.
Documentation
The authoritative documentation lives in spryker-docs. Start here:
- API Platform overview — concepts, architecture, and the resource generation workflow.
- Resource schemas —
*.resource.ymlreference. - Validation schemas —
*.validation.ymlreference. - Relationships — declaring includes between resources.
- CodeBucket support — region-specific resource variants.
- Testing — writing tests for API Platform resources.
- IDE integration — PHPStorm and VSCode setup for YAML autocomplete.
- Integration guide — installing and configuring API Platform in a project.
- Migration from Glue REST — moving legacy endpoints to API Platform.
- Troubleshooting — common issues and solutions.