diff --git a/config/class.yaml b/config/class.yaml
new file mode 100644
index 00000000..1de06806
--- /dev/null
+++ b/config/class.yaml
@@ -0,0 +1,25 @@
+services:
+ _defaults:
+ autowire: true
+ autoconfigure: true
+ public: false
+
+ # controllers are imported separately to make sure they're public
+ # and have a tag that allows actions to type-hint services
+ Pimcore\Bundle\StudioBackendBundle\Class\Controller\:
+ resource: '../src/Class/Controller'
+ public: true
+ tags: [ 'controller.service_arguments' ]
+
+ #
+ # Services
+ #
+ Pimcore\Bundle\StudioBackendBundle\Class\Service\FieldCollection\LayoutDefinitionServiceInterface:
+ class: Pimcore\Bundle\StudioBackendBundle\Class\Service\FieldCollection\LayoutDefinitionService
+
+
+ #
+ # Hydrators
+ #
+ Pimcore\Bundle\StudioBackendBundle\Class\Hydrator\FieldCollection\LayoutDefinitionHydratorInterface:
+ class: Pimcore\Bundle\StudioBackendBundle\Class\Hydrator\FieldCollection\LayoutDefinitionHydrator
\ No newline at end of file
diff --git a/src/Class/Controller/FieldCollection/LayoutController.php b/src/Class/Controller/FieldCollection/LayoutController.php
new file mode 100644
index 00000000..64bd5e2f
--- /dev/null
+++ b/src/Class/Controller/FieldCollection/LayoutController.php
@@ -0,0 +1,82 @@
+value],
+ )]
+ #[IdParameter(name: 'objectId', required: true)]
+ #[SuccessResponse(
+ description: 'class_field_collection_object_layout_success_response',
+ content: new CollectionJson(new GenericCollection(LayoutDefinition::class))
+ )]
+ #[DefaultResponses([
+ HttpResponseCodes::NOT_FOUND,
+ ])]
+ public function getFieldCollectionLayoutForObject(int $objectId): JsonResponse
+ {
+ $items = $this->layoutDefinitionService->getLayoutDefinitionsForObject($objectId);
+
+ return $this->getPaginatedCollection(
+ $this->serializer,
+ $items,
+ count($items),
+ );
+ }
+}
diff --git a/src/Class/Event/FieldCollection/LayoutDefinitionEvent.php b/src/Class/Event/FieldCollection/LayoutDefinitionEvent.php
new file mode 100644
index 00000000..66d41765
--- /dev/null
+++ b/src/Class/Event/FieldCollection/LayoutDefinitionEvent.php
@@ -0,0 +1,35 @@
+layoutDefinition);
+ }
+
+ public function getLayoutDefinition(): LayoutDefinition
+ {
+ return $this->layoutDefinition;
+ }
+}
diff --git a/src/Class/Hydrator/FieldCollection/LayoutDefinitionHydrator.php b/src/Class/Hydrator/FieldCollection/LayoutDefinitionHydrator.php
new file mode 100644
index 00000000..ddafa45c
--- /dev/null
+++ b/src/Class/Hydrator/FieldCollection/LayoutDefinitionHydrator.php
@@ -0,0 +1,46 @@
+getLayoutDefinitions();
+
+ return new LayoutDefinition(
+ $data->getKey(),
+ $layout->getDatatype(),
+ $data->getGroup(),
+ $layout->getName(),
+ $layout->getType(),
+ $layout->getRegion(),
+ $layout->getTitle(),
+ $layout->getWidth(),
+ $layout->getHeight(),
+ $layout->getCollapsible(),
+ $layout->getCollapsed(),
+ $layout->getChildren(),
+ );
+ }
+}
diff --git a/src/Class/Hydrator/FieldCollection/LayoutDefinitionHydratorInterface.php b/src/Class/Hydrator/FieldCollection/LayoutDefinitionHydratorInterface.php
new file mode 100644
index 00000000..f0691955
--- /dev/null
+++ b/src/Class/Hydrator/FieldCollection/LayoutDefinitionHydratorInterface.php
@@ -0,0 +1,28 @@
+key;
+ }
+
+ public function getGroup(): ?string
+ {
+ return $this->group;
+ }
+
+ public function getName(): ?string
+ {
+ return $this->name;
+ }
+
+ public function getType(): ?string
+ {
+ return $this->type;
+ }
+
+ public function getRegion(): ?string
+ {
+ return $this->region;
+ }
+
+ public function getTitle(): ?string
+ {
+ return $this->title;
+ }
+
+ public function getWidth(): int
+ {
+ return $this->width;
+ }
+
+ public function getHeight(): int
+ {
+ return $this->height;
+ }
+
+ public function isCollapsible(): bool
+ {
+ return $this->collapsible;
+ }
+
+ public function isCollapsed(): bool
+ {
+ return $this->collapsed;
+ }
+
+ public function getDatatype(): string
+ {
+ return $this->datatype;
+ }
+
+ public function getChildren(): array
+ {
+ return $this->children;
+ }
+}
diff --git a/src/Class/Service/FieldCollection/LayoutDefinitionService.php b/src/Class/Service/FieldCollection/LayoutDefinitionService.php
new file mode 100644
index 00000000..7aa5b9ad
--- /dev/null
+++ b/src/Class/Service/FieldCollection/LayoutDefinitionService.php
@@ -0,0 +1,99 @@
+dataObjectResolver->getById($dataObjectId);
+
+ if (!$dataObject) {
+ throw new NotFoundException('data Object', $dataObjectId);
+ }
+
+ $this->collectFieldCollectionTypes(
+ $this->classDefinitionResolver->getById($dataObject->getClassId())
+ );
+
+ $layoutDefinitions = [];
+ foreach ($this->fieldCollectionTypes as $fieldCollectionType) {
+ $layoutDefinitions[] = $this->getLayoutDefinitionByType($fieldCollectionType);
+ }
+
+ return $layoutDefinitions;
+ }
+
+ /**
+ * @throws Exception
+ */
+ private function getLayoutDefinitionByType(string $name): LayoutDefinition
+ {
+ $definition = $this->definitionResolver->getByKey($name);
+
+ if (!$definition) {
+ throw new NotFoundException('Field Collection Definition', $name);
+ }
+
+ $layoutDefinition = $this->layoutDefinitionHydrator->hydrate($definition);
+
+ $this->eventDispatcher->dispatch(
+ new LayoutDefinitionEvent($layoutDefinition),
+ LayoutDefinitionEvent::EVENT_NAME
+ );
+
+ return $layoutDefinition;
+ }
+
+ private function collectFieldCollectionTypes(ClassDefinitionInterface $classDefinition): void
+ {
+ foreach ($classDefinition->getFieldDefinitions() as $fieldDefinition) {
+ if ($fieldDefinition instanceof DataObject\ClassDefinition\Data\Fieldcollections) {
+ $this->fieldCollectionTypes = [...$this->fieldCollectionTypes, ...$fieldDefinition->getAllowedTypes()];
+ }
+ }
+ }
+}
diff --git a/src/Class/Service/FieldCollection/LayoutDefinitionServiceInterface.php b/src/Class/Service/FieldCollection/LayoutDefinitionServiceInterface.php
new file mode 100644
index 00000000..d8ea9c67
--- /dev/null
+++ b/src/Class/Service/FieldCollection/LayoutDefinitionServiceInterface.php
@@ -0,0 +1,31 @@
+value,
description: 'tag_authorization_description'
)]
+#[Tag(
+ name: Tags::ClassDefinition->value,
+ description: 'tag_class_description'
+)]
#[Tag(
name: Tags::DataObjects->value,
description: 'tag_dataobjects_description'
@@ -119,6 +123,7 @@ enum Tags: string
case AssetGrid = 'Asset Grid';
case AssetThumbnails = 'Asset Thumbnails';
case Authorization = 'Authorization';
+ case ClassDefinition = 'Class Definition';
case DataObjects = 'Data Objects';
case DataObjectsGrid = 'Data Object Grid';
case Dependencies = 'Dependencies';
diff --git a/translations/studio_api_docs.en.yaml b/translations/studio_api_docs.en.yaml
index 5cc6b1f7..85e20292 100644
--- a/translations/studio_api_docs.en.yaml
+++ b/translations/studio_api_docs.en.yaml
@@ -416,6 +416,7 @@ tag_assign_to_element_success_response: Successfully assigned tag to element
tag_assign_to_element_summary: Assign a tag to an element
tag_authorization_description: Session-based login via username and password or logout
and invalidate the session
+tag_class_description: Class definition operations
tag_batch_operation_to_elements_by_type_and_id_description: |
Batch assign/replace multiple tags of the given parent based on the {elementId} and {elementType} to the children.
Operation parameter {operation} must be one of the assignreplace.
@@ -599,4 +600,8 @@ user_default_key_bindings_summary: Get default key bindings
user_default_key_bindings_response: List of default key bindings
user_upload_image_summary: Upload user image
user_get_image_summary: Get user profile image
-user_get_image_success_response: User profile image
\ No newline at end of file
+user_get_image_success_response: User profile image
+class_field_collection_object_layout_description: |
+ Get all layouts from the field collection for an given object
+class_field_collection_object_layout_summary: Get all layouts from the field collection for an given object
+class_field_collection_object_layout_success_response: List of layouts
\ No newline at end of file