diff --git a/pom.xml b/pom.xml
index ccb8de3bfd4dcbb34e522ade41b81e7bbe5125cd..915ccea3e9f6dfbca7d73078bb0a325dc625d97e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,10 +89,6 @@
 			<artifactId>spring-boot-configuration-processor</artifactId>
 			<optional>true</optional>
 		</dependency>
-		<dependency>
-			<groupId>net.devh</groupId>
-			<artifactId>grpc-client-spring-boot-starter</artifactId>
-		</dependency>
 
 		<!-- ShedLock -->
 		<dependency>
diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
index 7962926bad3084bd5537279b6c4fdc166e046db6..cf4720b88a773d2153428371fc018d1d8638e72d 100644
--- a/src/main/helm/templates/deployment.yaml
+++ b/src/main/helm/templates/deployment.yaml
@@ -104,6 +104,10 @@ spec:
           - name: ozgcloud_administration_sync_organisationseinheiten_cron
             value: {{ .Values.ozgcloud.sync.organisationseinheiten.cron | quote }}
           {{- end }}
+          - name: grpc_client_zufi-manager_address
+            value: {{ .Values.zufiManager.address }}
+          - name: grpc_client_zufi-manager_negotiationType
+            value: {{ (.Values.zufiManager).grpcClientNegotiationType | default "TLS" }}
         envFrom:
           {{- if (.Values.database).useExternal }}
           - secretRef:
diff --git a/src/main/helm/templates/network_policy.yaml b/src/main/helm/templates/network_policy.yaml
index 1c8c51e0be101348d8e999960f0e0e98124d85c8..ba64d59e4918597d31d38d4598d5309a9287e3ff 100644
--- a/src/main/helm/templates/network_policy.yaml
+++ b/src/main/helm/templates/network_policy.yaml
@@ -28,6 +28,16 @@ spec:
 {{ toYaml . | indent 2 }}
 {{- end }}
   egress:
+    - to:
+        - namespaceSelector:
+            matchLabels:
+              kubernetes.io/metadata.name: "zufi"
+          podSelector:
+            matchLabels:
+              component: "zufi-server"
+      ports:
+        - port: 9090
+          protocol: TCP
     - to:
       - podSelector:
           matchLabels:
diff --git a/src/main/helm/templates/service_account.yaml b/src/main/helm/templates/service_account.yaml
index 0e13e6bcabf1933117c29487473453b63265922a..3bac8e223d1fd108b386d1f06ed4e9fb2284a67c 100644
--- a/src/main/helm/templates/service_account.yaml
+++ b/src/main/helm/templates/service_account.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
 # Ministerpräsidenten des Landes Schleswig-Holstein
 # Staatskanzlei
 # Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
diff --git a/src/main/helm/values.yaml b/src/main/helm/values.yaml
index 65c0a551f00d862d2432233e89c37a7051d3ee1d..6d9f58a3cdce518e86f0bca90594972ee87f2fd9 100644
--- a/src/main/helm/values.yaml
+++ b/src/main/helm/values.yaml
@@ -33,6 +33,9 @@ ozgcloud:
     api:
       user: administrationApiUser
 
+zufiManager:
+  address: zufi-server.zufi:9090
+
 image:
   repo: docker.ozg-sh.de
   name: administration
diff --git a/src/main/java/de/ozgcloud/admin/keycloak/AddGroupData.java b/src/main/java/de/ozgcloud/admin/keycloak/AddGroupData.java
index 2845e10babe0bed5eaf22a1b5d5bb043d0532a6b..bfef1afa5a70b06618372fcb6e7c1eb035f3e872 100644
--- a/src/main/java/de/ozgcloud/admin/keycloak/AddGroupData.java
+++ b/src/main/java/de/ozgcloud/admin/keycloak/AddGroupData.java
@@ -9,7 +9,6 @@ import lombok.ToString;
 @ToString
 public class AddGroupData {
 
-	private String parentId;
 	private String name;
 	private String organisationsEinheitId;
 }
diff --git a/src/main/java/de/ozgcloud/admin/keycloak/Group.java b/src/main/java/de/ozgcloud/admin/keycloak/Group.java
index 0bf5a9e19b39f24637d9cdd8ef037f6110247609..005a7ce23d0709ade874e9fad35e7be17906ceee 100644
--- a/src/main/java/de/ozgcloud/admin/keycloak/Group.java
+++ b/src/main/java/de/ozgcloud/admin/keycloak/Group.java
@@ -7,7 +7,7 @@ import lombok.Getter;
 import lombok.Singular;
 
 @Getter
-@Builder
+@Builder(toBuilder = true)
 public class Group {
 
 	private String id;
diff --git a/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java b/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java
index 4af927fa8481a073970825559f759b9234b72c90..a18a572526e3e4da1ca1bbc66433fe17266acedc 100644
--- a/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java
+++ b/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java
@@ -23,15 +23,6 @@ abstract class GroupMapper {
 
 	public abstract List<Group> fromGroupRepresentations(List<GroupRepresentation> groupRepresentations);
 
-	@AfterMapping
-	protected void deleteGroupsWithoutOrganisationsEinheitId(@MappingTarget List<Group> groups) {
-		groups.removeIf(this::isMissingOrganisationsEinheitId);
-	}
-
-	protected boolean isMissingOrganisationsEinheitId(Group group) {
-		return StringUtils.isBlank(group.getOrganisationsEinheitId());
-	}
-
 	@Mapping(target = "organisationsEinheitId", source = "attributes")
 	public abstract Group fromGroupRepresentation(GroupRepresentation groupRepresentation);
 
@@ -44,15 +35,24 @@ abstract class GroupMapper {
 			return null;
 		}
 		if (values.size() > 1 && values.stream().distinct().count() > 1) {
-			LOG.warn("Group contains multiple values for {}. The first one is taken.", keycloakApiProperties.getOrganisationsEinheitIdKey());
+			throw new GroupRepresentationMappingException("Group contains multiple values for organisationsEinheitId: %s".formatted(values));
 		}
 		return values.getFirst();
 	}
 
-	@Mapping(target = "attributes", expression = "java(getAttributes(groupToAdd))")
+	@AfterMapping
+	protected void deleteGroupsWithoutOrganisationsEinheitId(@MappingTarget List<Group> groups) {
+		groups.removeIf(this::isMissingOrganisationsEinheitId);
+	}
+
+	protected boolean isMissingOrganisationsEinheitId(Group group) {
+		return StringUtils.isBlank(group.getOrganisationsEinheitId());
+	}
+
+	@Mapping(target = "attributes", expression = "java(buildGroupAttributes(groupToAdd))")
 	public abstract GroupRepresentation toGroupRepresentation(AddGroupData groupToAdd);
 
-	Map<String, List<String>> getAttributes(AddGroupData groupToAdd) {
+	Map<String, List<String>> buildGroupAttributes(AddGroupData groupToAdd) {
 		var organisationsEinheitId = groupToAdd.getOrganisationsEinheitId();
 		return StringUtils.isNotBlank(organisationsEinheitId) ?
 				Map.of(keycloakApiProperties.getOrganisationsEinheitIdKey(), List.of(organisationsEinheitId)) :
diff --git a/src/main/java/de/ozgcloud/admin/keycloak/GroupRepresentationMappingException.java b/src/main/java/de/ozgcloud/admin/keycloak/GroupRepresentationMappingException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c07743ddf481a64e3d296309fbaa556fbab31f14
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/keycloak/GroupRepresentationMappingException.java
@@ -0,0 +1,8 @@
+package de.ozgcloud.admin.keycloak;
+
+public class GroupRepresentationMappingException extends RuntimeException {
+
+	public GroupRepresentationMappingException(String message) {
+		super(message);
+	}
+}
diff --git a/src/main/java/de/ozgcloud/admin/keycloak/KeycloakApiService.java b/src/main/java/de/ozgcloud/admin/keycloak/KeycloakApiService.java
index 057d0ab9622b949f7214008b131e956d76b70629..888f98c8b9acbecc3eaecf16cfbacd9dca176587 100644
--- a/src/main/java/de/ozgcloud/admin/keycloak/KeycloakApiService.java
+++ b/src/main/java/de/ozgcloud/admin/keycloak/KeycloakApiService.java
@@ -21,11 +21,11 @@ class KeycloakApiService {
 
 	public String addGroup(GroupRepresentation groupRepresentation) {
 		try (var response = groupsResource.add(groupRepresentation)) {
-			return getAddedResourceIdFromResponse(response);
+			return getCreatedResourceIdFromResponse(response);
 		}
 	}
 
-	String getAddedResourceIdFromResponse(Response response) {
+	String getCreatedResourceIdFromResponse(Response response) {
 		if (response.getStatus() == Response.Status.CREATED.getStatusCode()) {
 			return extractResourceIdFromLocationHeader(response.getHeaderString("Location"));
 		}
diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java
index 0b6bfbbfc86229fa798b1c43671a1af904233526..012a2343ca6c64140adfd28740791b94c1ec8769 100644
--- a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java
+++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java
@@ -31,7 +31,7 @@ public class OrganisationsEinheit {
 	@JsonIgnore
 	private String zufiId;
 	@JsonIgnore
-	private long lastSyncTimestamp;
+	private Long lastSyncTimestamp;
 	@JsonIgnore
 	private String parentId;
 	@JsonIgnore
diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRepository.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRepository.java
index 3f8e3c38963297d397cb05542479f4a8a1d99984..f32cbadfe751ab671151de99142112f22ff02671 100644
--- a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRepository.java
+++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRepository.java
@@ -25,6 +25,6 @@ interface OrganisationsEinheitRepository extends MongoRepository<OrganisationsEi
 	@Update("{'$set':  {'syncResult':  'DELETED'}}")
 	void setUnsyncedAsDeleted(long lastSyncTimestamp);
 
-	@Query("{'syncResult': { $eq: null }}")
+	@Query("{'syncResult': null }")
 	Stream<OrganisationsEinheit> findAllWithoutSyncResult();
 }
diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitSynchronizationException.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitSynchronizationException.java
new file mode 100644
index 0000000000000000000000000000000000000000..42944f0a41b1d5eb7cd1a724ab8e1792bc7da7de
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitSynchronizationException.java
@@ -0,0 +1,12 @@
+package de.ozgcloud.admin.organisationseinheit;
+
+public class OrganisationsEinheitSynchronizationException extends RuntimeException {
+
+	public OrganisationsEinheitSynchronizationException(String message) {
+		super(message);
+	}
+
+	public OrganisationsEinheitSynchronizationException(String message, Throwable cause) {
+		super(message, cause);
+	}
+}
diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/SyncService.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/SyncService.java
index 98139f6fa92396ba563328d59275744fadc6a802..a1c911a20d16d2cb4fdbbd707417180521c0bd9f 100644
--- a/src/main/java/de/ozgcloud/admin/organisationseinheit/SyncService.java
+++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/SyncService.java
@@ -23,14 +23,14 @@ class SyncService {
 	private final OrganisationsEinheitMapper organisationsEinheitMapper;
 
 	public void syncOrganisationsEinheitenFromKeycloak(long syncTimestamp) {
-		keycloakRemoteService.getGroupsWithOrganisationsEinheitId().forEach(group -> syncGroups(group, null, syncTimestamp));
+		keycloakRemoteService.getGroupsWithOrganisationsEinheitId().forEach(group -> syncGroupsWithSubGroups(group, null, syncTimestamp));
 		repository.setUnsyncedAsDeleted(syncTimestamp);
 	}
 
-	void syncGroups(Group group, OrganisationsEinheit parent, long syncTimestamp) {
+	void syncGroupsWithSubGroups(Group group, OrganisationsEinheit parent, long syncTimestamp) {
 		var synced = syncGroup(group, parent, syncTimestamp);
 		var saved = saveSyncedOrganisationsEinheit(synced);
-		group.getSubGroups().forEach(subGroup -> syncGroups(subGroup, saved, syncTimestamp));
+		group.getSubGroups().forEach(subGroup -> syncGroupsWithSubGroups(subGroup, saved, syncTimestamp));
 	}
 
 	OrganisationsEinheit syncGroup(Group group, OrganisationsEinheit parent, long syncTimestamp) {
@@ -89,28 +89,38 @@ class SyncService {
 	}
 
 	public void syncAddedOrganisationsEinheiten(long syncTimestamp) {
-		repository.findAllWithoutSyncResult().forEach(organisationsEinheit -> syncAddedOrganisationsEinheit(syncTimestamp, organisationsEinheit));
+		repository.findAllWithoutSyncResult().forEach(
+				organisationsEinheit -> syncAddedOrganisationsEinheit(organisationsEinheit, syncTimestamp));
 	}
 
-	void syncAddedOrganisationsEinheit(long syncTimestamp, OrganisationsEinheit organisationsEinheit) {
-		var addGroupData = organisationsEinheitMapper.toAddGroupData(organisationsEinheit);
-		var keycloakId = addGroupInKeycloak(addGroupData);
-		if (keycloakId.isPresent()) {
-			var updatedOrganisationsEinheit = organisationsEinheit.toBuilder()
-					.keycloakId(keycloakId.get())
-					.syncResult(SyncResult.OK)
-					.lastSyncTimestamp(syncTimestamp)
-					.build();
-			repository.save(updatedOrganisationsEinheit);
+	void syncAddedOrganisationsEinheit(OrganisationsEinheit organisationsEinheit, long syncTimestamp) {
+		addAsGroupInKeycloak(organisationsEinheit).ifPresent(
+				addedGroupId -> updateAfterSuccessfulGroupCreation(organisationsEinheit, addedGroupId, syncTimestamp));
+	}
+
+	Optional<String> addAsGroupInKeycloak(OrganisationsEinheit organisationsEinheit) {
+		if (organisationsEinheit.getParentId() != null) {
+			throw new OrganisationsEinheitSynchronizationException(
+					"Organisationseinheit %s has parent".formatted(organisationsEinheit.getOrganisationsEinheitId()));
 		}
+		var addGroupData = organisationsEinheitMapper.toAddGroupData(organisationsEinheit);
+		return addGroupInKeycloak(addGroupData);
+	}
+
+	void updateAfterSuccessfulGroupCreation(OrganisationsEinheit organisationsEinheit, String keycloakId, long syncTimestamp) {
+		var updatedOrganisationsEinheit = organisationsEinheit.toBuilder()
+				.keycloakId(keycloakId)
+				.syncResult(SyncResult.OK)
+				.lastSyncTimestamp(syncTimestamp)
+				.build();
+		repository.save(updatedOrganisationsEinheit);
 	}
 
 	Optional<String> addGroupInKeycloak(AddGroupData addGroupData) {
 		try {
 			return Optional.of(keycloakRemoteService.addGroup(addGroupData));
 		} catch (ResourceCreationException e) {
-			LOG.error("Error adding group %s in Keycloak".formatted(addGroupData), e);
-			return Optional.empty();
+			throw new OrganisationsEinheitSynchronizationException("Error creating group %s in Keycloak".formatted(addGroupData), e);
 		}
 	}
 }
diff --git a/src/main/resources/application-remotekc.yaml b/src/main/resources/application-remotekc.yaml
index a4cd02efb0e33fb73ccaf95e1478973185b12261..e64923222403088b888536380a901d46bb3fc442 100644
--- a/src/main/resources/application-remotekc.yaml
+++ b/src/main/resources/application-remotekc.yaml
@@ -6,4 +6,3 @@ ozgcloud:
   keycloak:
     api:
       user: administrationApiUser
-      password: 4hVe-qWRM4ZwMdQ
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index af6a93ebdb869b45fc3c0be85fa38dbe821a0683..ddb50199effa7b74f3825194c43a5780fc4706e7 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -88,5 +88,5 @@ ozgcloud:
 grpc:
   client:
     zufi-manager:
-      address: static://127.0.0.1:9190
+      address: static://127.0.0.1:9090
       negotiationType: TLS
\ No newline at end of file
diff --git a/src/test/helm/network_policy_test.yaml b/src/test/helm/network_policy_test.yaml
index 427fafd41265488ffe1002a9746373156b7a9718..6db0ccf63232ae8e01f74badd5c11f29245c5f70 100644
--- a/src/test/helm/network_policy_test.yaml
+++ b/src/test/helm/network_policy_test.yaml
@@ -83,10 +83,20 @@ tests:
                 - protocol: TCP
                   port: 8081
             egress:
+              - to:
+                  - namespaceSelector:
+                      matchLabels:
+                        kubernetes.io/metadata.name: "zufi"
+                    podSelector:
+                      matchLabels:
+                        component: "zufi-server"
+                ports:
+                  - port: 9090
+                    protocol: TCP
               - to:
                   - podSelector:
                       matchLabels:
-                        component: ozgcloud-mongodb
+                        component: "ozgcloud-mongodb"
                 ports:
                   - port: 27017
                     protocol: TCP
diff --git a/src/test/java/de/ozgcloud/admin/keycloak/AddGroupDataTestFactory.java b/src/test/java/de/ozgcloud/admin/keycloak/AddGroupDataTestFactory.java
index b53d872617b553a2c708e6b653905231889af445..cea95944ffe15491d5a60ead097db8a8a29c4989 100644
--- a/src/test/java/de/ozgcloud/admin/keycloak/AddGroupDataTestFactory.java
+++ b/src/test/java/de/ozgcloud/admin/keycloak/AddGroupDataTestFactory.java
@@ -2,7 +2,6 @@ package de.ozgcloud.admin.keycloak;
 
 public class AddGroupDataTestFactory {
 
-	public static final String PARENT_ID = GroupRepresentationTestFactory.ID;
 	public static final String NAME = GroupRepresentationTestFactory.NAME;
 	public static final String ORGANISATIONS_EINHEIT_ID = GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID;
 
@@ -12,7 +11,6 @@ public class AddGroupDataTestFactory {
 
 	public static AddGroupData.AddGroupDataBuilder createBuilder() {
 		return new AddGroupData.AddGroupDataBuilder()
-				.parentId(PARENT_ID)
 				.name(NAME)
 				.organisationsEinheitId(ORGANISATIONS_EINHEIT_ID);
 	}
diff --git a/src/test/java/de/ozgcloud/admin/keycloak/GroupMapperTest.java b/src/test/java/de/ozgcloud/admin/keycloak/GroupMapperTest.java
index adaddc58f2a88a674a6e66e2fba85c698ba81570..82b47bca310517e47c6ac5b812c4abc9aef66db9 100644
--- a/src/test/java/de/ozgcloud/admin/keycloak/GroupMapperTest.java
+++ b/src/test/java/de/ozgcloud/admin/keycloak/GroupMapperTest.java
@@ -4,6 +4,7 @@ import static de.ozgcloud.admin.keycloak.GroupRepresentationTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -13,8 +14,11 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.junit.jupiter.params.provider.ValueSource;
 import org.keycloak.representations.idm.GroupRepresentation;
 import org.mapstruct.factory.Mappers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
@@ -28,42 +32,64 @@ class GroupMapperTest {
 	private GroupMapper mapper = Mappers.getMapper(GroupMapper.class);
 
 	@Nested
-	class TestGetOrganisationsEinheitId {
+	class TestFromGroupRepresentations {
+
+		private final GroupRepresentation groupRepresentation = GroupRepresentationTestFactory.create();
+
+		@Captor
+		private ArgumentCaptor<List<Group>> groupsCaptor;
 
 		@Test
-		void shouldReturnNullIfAttributesAreNull() {
-			var result = mapper.getOrganisationsEinheitId(null);
+		void shouldMapFromGroupRepresentation() {
+			givenMappedGroupWithOrganisationsEinheitId();
 
-			assertThat(result).isNull();
+			callMapper();
+
+			verify(mapper).fromGroupRepresentation(groupRepresentation);
 		}
 
 		@Test
-		void shouldReturnNullIfAttributeIsAbsent() {
-			givenOrganisationsEinheitIdProperty();
+		void shouldReturnListWithMappedGroupRepresentation() {
+			var group = givenMappedGroupWithOrganisationsEinheitId();
 
-			var result = mapper.getOrganisationsEinheitId(Map.of("dummy-attribute", List.of("123")));
+			var groups = callMapper();
 
-			assertThat(result).isNull();
+			assertThat(groups).containsExactly(group);
 		}
 
-		@Test
-		void shouldReturnOrganisationsEinheitId() {
-			givenOrganisationsEinheitIdProperty();
-			var value = GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID;
-			var result = mapper.getOrganisationsEinheitId(Map.of(ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, List.of(value)));
+		@ParameterizedTest
+		@NullAndEmptySource
+		void shouldReturnEmptyList(String organisationsEinheitId) {
+			givenMappedGroupWithOrganisationsEinheitId(organisationsEinheitId);
 
-			assertThat(result).isEqualTo(value);
+			var groups = callMapper();
+
+			assertThat(groups).isEmpty();
 		}
 
 		@Test
-		void shouldReturnFirstValueIfMultipleAreAvailable() {
-			givenOrganisationsEinheitIdProperty();
-			var value = GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID;
-			var value2 = UUID.randomUUID().toString();
+		void shouldDeleteGroupsWithoutOrganisationsEinheitId() {
+			var group = givenMappedGroupWithOrganisationsEinheitId();
 
-			var result = mapper.getOrganisationsEinheitId(Map.of(ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, List.of(value, value2)));
+			callMapper();
 
-			assertThat(result).isEqualTo(value);
+			verify(mapper).deleteGroupsWithoutOrganisationsEinheitId(groupsCaptor.capture());
+			assertThat(groupsCaptor.getValue()).containsExactly(group);
+		}
+
+		private Group givenMappedGroupWithOrganisationsEinheitId() {
+			var group = GroupTestFactory.create();
+			doReturn(group).when(mapper).fromGroupRepresentation(groupRepresentation);
+			return group;
+		}
+
+		private void givenMappedGroupWithOrganisationsEinheitId(String id) {
+			var group = GroupTestFactory.createBuilder().organisationsEinheitId(id).build();
+			doReturn(group).when(mapper).fromGroupRepresentation(groupRepresentation);
+		}
+
+		private List<Group> callMapper() {
+			return mapper.fromGroupRepresentations(List.of(groupRepresentation));
 		}
 	}
 
@@ -122,51 +148,101 @@ class GroupMapperTest {
 	}
 
 	@Nested
-	class TestFromGroupRepresentations {
+	class TestGetOrganisationsEinheitId {
 
-		private final GroupRepresentation groupRepresentation = GroupRepresentationTestFactory.create();
+		@Test
+		void shouldReturnNullIfAttributesAreNull() {
+			var result = mapper.getOrganisationsEinheitId(null);
+
+			assertThat(result).isNull();
+		}
 
 		@Test
-		void shouldMapFromGroupRepresentation() {
-			givenMappedGroupWithOrganisationsEinheitId();
+		void shouldReturnNullIfAttributeIsAbsent() {
+			givenOrganisationsEinheitIdProperty();
 
-			callMapper();
+			var result = mapper.getOrganisationsEinheitId(Map.of("dummy-attribute", List.of("123")));
 
-			verify(mapper).fromGroupRepresentation(groupRepresentation);
+			assertThat(result).isNull();
 		}
 
 		@Test
-		void shouldReturnListWithMappedGroupRepresentation() {
-			var group = givenMappedGroupWithOrganisationsEinheitId();
+		void shouldReturnOrganisationsEinheitId() {
+			givenOrganisationsEinheitIdProperty();
+			var value = GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID;
+			var result = mapper.getOrganisationsEinheitId(Map.of(ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, List.of(value)));
 
-			var groups = callMapper();
+			assertThat(result).isEqualTo(value);
+		}
+
+		@Test
+		void shouldThrowExceptionIfMultipleValuesAreAvailable() {
+			givenOrganisationsEinheitIdProperty();
+			var value = GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID;
+			var value2 = UUID.randomUUID().toString();
+
+			assertThatExceptionOfType(GroupRepresentationMappingException.class)
+					.isThrownBy(() ->  mapper.getOrganisationsEinheitId(Map.of(ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, List.of(value, value2))))
+					.withMessage("Group contains multiple values for organisationsEinheitId: %s", List.of(value, value2));
+		}
+	}
+
+	@Nested
+	class TestDeleteGroupsWithoutOrganisationsEinheitId {
+
+		private final Group group = GroupTestFactory.create();
+		private final List<Group> groups = new ArrayList<>();
+
+		@BeforeEach
+		void init() {
+			groups.add(group);
+		}
+
+		@Test
+		void shouldCheckIfGroupHasOrganisationsEinheitId() {
+			mapper.deleteGroupsWithoutOrganisationsEinheitId(groups);
+
+			verify(mapper).isMissingOrganisationsEinheitId(group);
+		}
+
+		@Test
+		void shouldKeepGroupsWithOrganisationsEinheitId() {
+			doReturn(false).when(mapper).isMissingOrganisationsEinheitId(group);
+
+			mapper.deleteGroupsWithoutOrganisationsEinheitId(groups);
 
 			assertThat(groups).containsExactly(group);
 		}
 
-		@ParameterizedTest
-		@NullAndEmptySource
-		void shouldReturnEmptyList(String organisationsEinheitId) {
-			givenMappedGroupWithOrganisationsEinheitId(organisationsEinheitId);
+		@Test
+		void shouldRemoveGroupsWithoutOrganisationsEinheitId() {
+			doReturn(true).when(mapper).isMissingOrganisationsEinheitId(group);
 
-			var groups = callMapper();
+			mapper.deleteGroupsWithoutOrganisationsEinheitId(groups);
 
 			assertThat(groups).isEmpty();
 		}
+	}
 
-		private Group givenMappedGroupWithOrganisationsEinheitId() {
-			var group = GroupTestFactory.create();
-			doReturn(group).when(mapper).fromGroupRepresentation(groupRepresentation);
-			return group;
-		}
+	@Nested
+	class TestIsMissingOrganisationsEinheitId {
 
-		private void givenMappedGroupWithOrganisationsEinheitId(String id) {
-			var group = GroupTestFactory.createBuilder().organisationsEinheitId(id).build();
-			doReturn(group).when(mapper).fromGroupRepresentation(groupRepresentation);
+		@ParameterizedTest
+		@ValueSource(strings = " ")
+		@NullAndEmptySource
+		void shouldReturnTrueIfIdIsBlank(String organisationsEinheitId) {
+			var group = GroupTestFactory.createBuilder().organisationsEinheitId(organisationsEinheitId).build();
+
+			var isMissing = mapper.isMissingOrganisationsEinheitId(group);
+
+			assertThat(isMissing).isTrue();
 		}
 
-		private List<Group> callMapper() {
-			return mapper.fromGroupRepresentations(List.of(groupRepresentation));
+		@Test
+		void shouldReturnFalseIfIdIsSet() {
+			var isMissing = mapper.isMissingOrganisationsEinheitId(GroupTestFactory.create());
+
+			assertThat(isMissing).isFalse();
 		}
 	}
 
@@ -177,14 +253,7 @@ class GroupMapperTest {
 
 		@BeforeEach
 		void init() {
-			doReturn(ATTRIBUTES).when(mapper).getAttributes(addGroupData);
-		}
-
-		@Test
-		void shouldSetParentId() {
-			var groupRepresentation = callMapper();
-
-			assertThat(groupRepresentation.getParentId()).isEqualTo(addGroupData.getParentId());
+			doReturn(ATTRIBUTES).when(mapper).buildGroupAttributes(addGroupData);
 		}
 
 		@Test
@@ -202,10 +271,10 @@ class GroupMapperTest {
 		}
 
 		@Test
-		void shouldGetAttributes() {
+		void shouldBuildGroupAttributes() {
 			callMapper();
 
-			verify(mapper).getAttributes(addGroupData);
+			verify(mapper).buildGroupAttributes(addGroupData);
 		}
 
 		@Test
@@ -221,14 +290,14 @@ class GroupMapperTest {
 	}
 
 	@Nested
-	class TestGetAttributes {
+	class TestBuildGroupAttributes {
 
 		@ParameterizedTest
 		@NullAndEmptySource
 		void shouldReturnEmptyMap(String organisationsEinheitId) {
 			var addGroupData = AddGroupDataTestFactory.createBuilder().organisationsEinheitId(organisationsEinheitId).build();
 
-			var attributes = mapper.getAttributes(addGroupData);
+			var attributes = mapper.buildGroupAttributes(addGroupData);
 
 			assertThat(attributes).isEmpty();
 		}
@@ -237,7 +306,7 @@ class GroupMapperTest {
 		void shouldAddOrganisationsEinheitIdToAttributes() {
 			givenOrganisationsEinheitIdProperty();
 
-			var attributes = mapper.getAttributes(AddGroupDataTestFactory.create());
+			var attributes = mapper.buildGroupAttributes(AddGroupDataTestFactory.create());
 
 			assertThat(attributes).hasSize(1).containsEntry(ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, List.of(GroupTestFactory.ORGANISATIONS_EINHEIT_ID));
 		}
diff --git a/src/test/java/de/ozgcloud/admin/keycloak/GroupRepresentationTestFactory.java b/src/test/java/de/ozgcloud/admin/keycloak/GroupRepresentationTestFactory.java
index 67dcc55771e8d52ae9f4d926e9568a22d47795ac..034f962513dc0ffefe78f26ab9d7755281d763a0 100644
--- a/src/test/java/de/ozgcloud/admin/keycloak/GroupRepresentationTestFactory.java
+++ b/src/test/java/de/ozgcloud/admin/keycloak/GroupRepresentationTestFactory.java
@@ -13,6 +13,7 @@ class GroupRepresentationTestFactory {
 	public static final String ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE = "organisationseinheitId";
 
 	public static final String ID = UUID.randomUUID().toString();
+	public static final String PARENT_ID = UUID.randomUUID().toString();
 	public static final String NAME = LoremIpsum.getInstance().getName();
 	public static final String ORGANISATIONS_EINHEIT_ID = UUID.randomUUID().toString();
 	public static final Map<String, List<String>> ATTRIBUTES = Map.of(ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, List.of(ORGANISATIONS_EINHEIT_ID));
@@ -43,6 +44,7 @@ class GroupRepresentationTestFactory {
 		if (withId) {
 			groupRepresentation.setId(ID);
 		}
+		groupRepresentation.setParentId(PARENT_ID);
 		groupRepresentation.setName(NAME);
 		groupRepresentation.setAttributes(ATTRIBUTES);
 		groupRepresentation.setSubGroups(List.of(createSubGroup(withId)));
@@ -54,6 +56,7 @@ class GroupRepresentationTestFactory {
 		if (withId) {
 			groupRepresentation.setId(SUB_GROUP_ID);
 		}
+		groupRepresentation.setParentId(ID);
 		groupRepresentation.setName(SUB_GROUP_NAME);
 		groupRepresentation.setAttributes(SUB_GROUP_ATTRIBUTES);
 		return groupRepresentation;
diff --git a/src/test/java/de/ozgcloud/admin/keycloak/KeycloakApiServiceITCase.java b/src/test/java/de/ozgcloud/admin/keycloak/KeycloakApiServiceITCase.java
index 848bc65b7ba24f6fd02eb89ea90d6afe441a4141..f2c7dd6c83ee9651cca09c17ad7eda8927ac94eb 100644
--- a/src/test/java/de/ozgcloud/admin/keycloak/KeycloakApiServiceITCase.java
+++ b/src/test/java/de/ozgcloud/admin/keycloak/KeycloakApiServiceITCase.java
@@ -146,7 +146,7 @@ class KeycloakApiServiceITCase {
 		}
 
 		@Test
-		void shouldNotAddSubgroups() {
+		void shouldNotAddSubgroupsOfAddedGroup() {
 			var groupToAdd = createUniqueGroupRepresentation("shouldNotAddSubgroups");
 
 			var groupId = service.addGroup(groupToAdd);
@@ -155,10 +155,12 @@ class KeycloakApiServiceITCase {
 					.asList().isEmpty();
 		}
 
-		private GroupRepresentation createUniqueGroupRepresentation(String suffix) {
+		private GroupRepresentation createUniqueGroupRepresentation(String nameSuffix) {
 			// LoremIpsum does not guarantee unique results when called repeatedly
-			var groupName = "%s (%s)".formatted(LoremIpsum.getInstance().getName(), suffix);
-			return GroupRepresentationTestFactory.createWithoutId(groupName);
+			var groupName = "%s (%s)".formatted(LoremIpsum.getInstance().getName(), nameSuffix);
+			var group = GroupRepresentationTestFactory.createWithoutId(groupName);
+			group.setParentId(null);
+			return group;
 		}
 
 		private Optional<GroupRepresentation> findGroupInKeycloak(String groupId) {
diff --git a/src/test/java/de/ozgcloud/admin/keycloak/KeycloakApiServiceTest.java b/src/test/java/de/ozgcloud/admin/keycloak/KeycloakApiServiceTest.java
index ffded7cebae2a78c00c622ba341eb840eec4f760..ce9ed1256d94d81e5e04e820fe2436bfdc34b168 100644
--- a/src/test/java/de/ozgcloud/admin/keycloak/KeycloakApiServiceTest.java
+++ b/src/test/java/de/ozgcloud/admin/keycloak/KeycloakApiServiceTest.java
@@ -3,6 +3,8 @@ package de.ozgcloud.admin.keycloak;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
+import java.util.List;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -26,16 +28,37 @@ class KeycloakApiServiceTest {
 	@Mock
 	private Response response;
 
+	@Nested
+	class TestGetAllGroups {
+
+		@Test
+		void shouldCallGroupsResource() {
+			service.getAllGroups();
+
+			verify(groupsResource).groups("", 0, Integer.MAX_VALUE, false);
+		}
+
+		@Test
+		void shouldReturnGroupRepresentations() {
+			var groupRepresentation = GroupRepresentationTestFactory.create();
+			when(groupsResource.groups("", 0, Integer.MAX_VALUE, false)).thenReturn(List.of(groupRepresentation));
+
+			var gotGroupRepresentations = service.getAllGroups();
+
+			assertThat(gotGroupRepresentations).containsExactly(groupRepresentation);
+		}
+	}
+
 	@Nested
 	class TestAddGroup {
 
 		private final GroupRepresentation groupRepresentation = GroupRepresentationTestFactory.create();
-		private final String RESOURCE_ID = GroupRepresentationTestFactory.create().getId();
+		private final String resourceId = GroupRepresentationTestFactory.create().getId();
 
 		@BeforeEach
 		void init() {
 			when(groupsResource.add(groupRepresentation)).thenReturn(response);
-			doReturn(RESOURCE_ID).when(service).getAddedResourceIdFromResponse(response);
+			doReturn(resourceId).when(service).getCreatedResourceIdFromResponse(response);
 		}
 
 		@Test
@@ -49,14 +72,14 @@ class KeycloakApiServiceTest {
 		void shouldGetAddedResourceIdFromResponse() {
 			callService();
 
-			verify(service).getAddedResourceIdFromResponse(response);
+			verify(service).getCreatedResourceIdFromResponse(response);
 		}
 
 		@Test
 		void shouldReturnAddedResourceId() {
 			var id = callService();
 
-			assertThat(id).isEqualTo(RESOURCE_ID);
+			assertThat(id).isEqualTo(resourceId);
 		}
 
 		private String callService() {
@@ -65,10 +88,10 @@ class KeycloakApiServiceTest {
 	}
 
 	@Nested
-	class TestGetAddedResourceIdFromResponse {
+	class TestGetCreatedResourceIdFromResponse {
 
-		private final String RESOURCE_ID = GroupRepresentationTestFactory.create().getId();
-		private final String LOCATION = LoremIpsum.getInstance().getUrl();
+		private final String resourceId = GroupRepresentationTestFactory.create().getId();
+		private final String location = LoremIpsum.getInstance().getUrl();
 
 		@Test
 		void shouldExtractResourceIdFromLocationHeader() {
@@ -76,7 +99,7 @@ class KeycloakApiServiceTest {
 
 			callService();
 
-			verify(service).extractResourceIdFromLocationHeader(LOCATION);
+			verify(service).extractResourceIdFromLocationHeader(location);
 		}
 
 		@Test
@@ -85,7 +108,7 @@ class KeycloakApiServiceTest {
 
 			var id = callService();
 
-			assertThat(id).isEqualTo(RESOURCE_ID);
+			assertThat(id).isEqualTo(resourceId);
 		}
 
 		@Test
@@ -98,8 +121,8 @@ class KeycloakApiServiceTest {
 
 		private void givenResponseCreated() {
 			when(response.getStatus()).thenReturn(201);
-			when(response.getHeaderString("Location")).thenReturn(LOCATION);
-			doReturn(RESOURCE_ID).when(service).extractResourceIdFromLocationHeader(LOCATION);
+			when(response.getHeaderString("Location")).thenReturn(location);
+			doReturn(resourceId).when(service).extractResourceIdFromLocationHeader(location);
 		}
 
 		private void givenResponseUnauthorized() {
@@ -108,21 +131,21 @@ class KeycloakApiServiceTest {
 		}
 
 		private String callService() {
-			return service.getAddedResourceIdFromResponse(response);
+			return service.getCreatedResourceIdFromResponse(response);
 		}
 	}
 
 	@Nested
 	class TestExtractResourceIdFromLocationHeader {
 
-		private final String RESOURCE_ID = GroupRepresentationTestFactory.create().getId();
-		private final String LOCATION = "https://keycloak-url.test/admin/realms/test/groups/" + RESOURCE_ID;
+		private final String resourceId = GroupRepresentationTestFactory.create().getId();
+		private final String location = "https://keycloak-url.test/admin/realms/test/groups/" + resourceId;
 
 		@Test
 		void shouldReturnId() {
-			var id = service.extractResourceIdFromLocationHeader(LOCATION);
+			var id = service.extractResourceIdFromLocationHeader(location);
 
-			assertThat(id).isEqualTo(RESOURCE_ID);
+			assertThat(id).isEqualTo(resourceId);
 		}
 	}
 }
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitControllerTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitControllerTest.java
index 06f4ce43a415aaa113d9505bcf686942a9a8be30..fbf00adebbb5aeb5e7b8c5edd6f2a6ce4d76f09f 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitControllerTest.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitControllerTest.java
@@ -96,10 +96,12 @@ class OrganisationsEinheitControllerTest {
 	class TestGetById {
 
 		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
+		private final EntityModel<OrganisationsEinheit> entityModel = EntityModel.of(organisationsEinheit);
 
 		@BeforeEach
 		void setUp() {
 			when(organisationsEinheitService.getOrganisationsEinheitById(OrganisationsEinheitTestFactory.ID)).thenReturn(organisationsEinheit);
+			when(assembler.toModel(organisationsEinheit)).thenReturn(entityModel);
 		}
 
 		@Test
@@ -122,6 +124,13 @@ class OrganisationsEinheitControllerTest {
 			doRequest().andExpect(status().isOk());
 		}
 
+		@Test
+		void shouldReturnEntityModel() {
+			var response = controller.getById(OrganisationsEinheitTestFactory.ID);
+
+			assertThat(response).isEqualTo(entityModel);
+		}
+
 		@SneakyThrows
 		private ResultActions doRequest() {
 			return mockMvc.perform(get(OrganisationsEinheitController.PATH + "/" + OrganisationsEinheitTestFactory.ID));
@@ -131,11 +140,15 @@ class OrganisationsEinheitControllerTest {
 	@Nested
 	class TestGetChildren {
 
-		private final List<OrganisationsEinheit> children = List.of(OrganisationsEinheitTestFactory.create());
+		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
+		private final List<OrganisationsEinheit> children = List.of(organisationsEinheit);
+		private final CollectionModel<EntityModel<OrganisationsEinheit>> collectionModel = CollectionModel.of(
+				List.of(EntityModel.of(organisationsEinheit)));
 
 		@BeforeEach
 		void setUp() {
 			when(organisationsEinheitService.getChildren(OrganisationsEinheitTestFactory.ID)).thenReturn(children);
+			when(assembler.toChildrenCollectionModel(OrganisationsEinheitTestFactory.ID, children)).thenReturn(collectionModel);
 		}
 
 		@Test
@@ -158,6 +171,13 @@ class OrganisationsEinheitControllerTest {
 			verify(assembler).toChildrenCollectionModel(OrganisationsEinheitTestFactory.ID, children);
 		}
 
+		@Test
+		void shouldReturnCollectionModel() {
+			var response = controller.getChildren(OrganisationsEinheitTestFactory.ID);
+
+			assertThat(response).isEqualTo(collectionModel);
+		}
+
 		@SneakyThrows
 		private ResultActions doRequest() {
 			return mockMvc.perform(get(OrganisationsEinheitController.PATH + "/" + OrganisationsEinheitTestFactory.ID + "/children"));
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapperTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapperTest.java
index 10ee3a2de7fd8c740093d84f0444b90cf7b9d19a..53ec27998c68c86ce3dcdb7b91a1a8ba77fb8c20 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapperTest.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapperTest.java
@@ -3,6 +3,7 @@ package de.ozgcloud.admin.organisationseinheit;
 import static org.assertj.core.api.Assertions.*;
 
 import java.util.Collections;
+import java.util.Objects;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -21,23 +22,23 @@ class OrganisationsEinheitMapperTest {
 		void shouldMap() {
 			var mapped = mapper.fromGrpc(GrpcOrganisationsEinheitTestFactory.create());
 
-			assertThat(mapped).extracting(
-					OrganisationsEinheit::getName,
-					OrganisationsEinheit::getOrganisationsEinheitId,
-					OrganisationsEinheit::getZufiId,
-					OrganisationsEinheit::getParentId,
-					OrganisationsEinheit::getSyncResult,
-					OrganisationsEinheit::getSettings,
-					OrganisationsEinheit::getChildren
-			).containsExactly(
-					OrganisationsEinheitTestFactory.NAME,
-					OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID,
-					OrganisationsEinheitTestFactory.ZUFI_ID,
-					null,
-					null,
-					null,
-					Collections.emptyList()
-			);
+			assertThat(mapped)
+					.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+					.extracting(
+							OrganisationsEinheit::getName,
+							OrganisationsEinheit::getOrganisationsEinheitId,
+							OrganisationsEinheit::getZufiId,
+							OrganisationsEinheit::getParentId,
+							OrganisationsEinheit::getSyncResult,
+							OrganisationsEinheit::getChildren
+					).containsExactly(
+							OrganisationsEinheitTestFactory.NAME,
+							OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID,
+							OrganisationsEinheitTestFactory.ZUFI_ID,
+							null,
+							null,
+							Collections.emptyList()
+					);
 		}
 	}
 
@@ -49,11 +50,9 @@ class OrganisationsEinheitMapperTest {
 			var mapped = mapper.toAddGroupData(OrganisationsEinheitTestFactory.create());
 
 			assertThat(mapped).extracting(
-					AddGroupData::getParentId,
 					AddGroupData::getName,
 					AddGroupData::getOrganisationsEinheitId
 			).containsExactly(
-					OrganisationsEinheitTestFactory.PARENT_ID,
 					OrganisationsEinheitTestFactory.NAME,
 					OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID
 			);
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssemblerTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssemblerTest.java
index d22dfcc1cec283ada2166c4402f1fd20fa711b0f..51c34967555f7f69218f28da26d4e48fd1a8701e 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssemblerTest.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssemblerTest.java
@@ -11,6 +11,8 @@ import java.util.UUID;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Spy;
 import org.springframework.hateoas.CollectionModel;
@@ -82,6 +84,10 @@ class OrganisationsEinheitModelAssemblerTest {
 		private CollectionModel<EntityModel<OrganisationsEinheit>> childrenCollectionModel;
 		@Spy
 		private final HalModelBuilder halModelBuilder = HalModelBuilder.emptyHalModel();
+		@Captor
+		private ArgumentCaptor<LinkRelation> linkRelationArgumentCaptor;
+		@Captor
+		private ArgumentCaptor<Collection<EntityModel<OrganisationsEinheit>>> collectionModelContentArgumentCaptor;
 
 		@BeforeEach
 		void setUp() {
@@ -89,8 +95,7 @@ class OrganisationsEinheitModelAssemblerTest {
 			childOrganisationsEinheit = OrganisationsEinheitTestFactory.createBuilder().id(UUID.randomUUID().toString())
 					.parentId(parentOrganisationsEinheit.getId()).build();
 			parentOrganisationsEinheit = parentOrganisationsEinheit.toBuilder().child(childOrganisationsEinheit).build();
-			childrenCollectionModel = CollectionModel.of(
-					List.of(EntityModel.of(childOrganisationsEinheit)));
+			childrenCollectionModel = CollectionModel.of(List.of(EntityModel.of(childOrganisationsEinheit)));
 			doReturn(childrenCollectionModel).when(assembler)
 					.toChildrenCollectionModel(parentOrganisationsEinheit.getId(), parentOrganisationsEinheit.getChildren());
 		}
@@ -106,7 +111,9 @@ class OrganisationsEinheitModelAssemblerTest {
 		void shouldEmbedChildrenModels() {
 			assembler.embedChildOrganisationsEinheiten(parentOrganisationsEinheit, halModelBuilder);
 
-			verify(halModelBuilder).embed(any(Collection.class), any(LinkRelation.class));
+			verify(halModelBuilder).embed(collectionModelContentArgumentCaptor.capture(), linkRelationArgumentCaptor.capture());
+			assertThat(collectionModelContentArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(childrenCollectionModel.getContent());
+			assertThat(linkRelationArgumentCaptor.getValue().toString()).isEqualTo(REL_CHILD_ORGANISATIONS_EINHEITEN);
 		}
 
 		@Test
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRepositoryITCase.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRepositoryITCase.java
index 9267fc3b7ae6a09af7d243983c56371cbe2656ee..d72ba698910c33fbdfff6ac74f2fec5dbefc0fef 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRepositoryITCase.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRepositoryITCase.java
@@ -112,7 +112,7 @@ class OrganisationsEinheitRepositoryITCase {
 		}
 
 		@Test
-		void shouldReturnEmptyOnNotFoundSyncResultNull() {
+		void shouldReturnEmptyOnSyncResultNull() {
 			operations.save(OrganisationsEinheitTestFactory.createBuilder().id(null).syncResult(null).build());
 
 			var organisationsEinheit = repository.findSyncedByKeycloakId(OrganisationsEinheitTestFactory.KEYCLOAK_ID);
@@ -146,12 +146,12 @@ class OrganisationsEinheitRepositoryITCase {
 		private final OrganisationsEinheit deleted1 = OrganisationsEinheitTestFactory.createBuilder()
 				.id(null)
 				.organisationsEinheitId(DELETED_ORGANISATIONS_EINHEIT_ID_1)
-				.lastSyncTimestamp(Instant.now().minusSeconds(300).toEpochMilli())
+				.lastSyncTimestamp(OrganisationsEinheitTestFactory.LAST_SYNC_UPDATE - 1)
 				.build();
 		private final OrganisationsEinheit deleted2 = OrganisationsEinheitTestFactory.createBuilder()
 				.id(null)
 				.organisationsEinheitId(DELETED_ORGANISATIONS_EINHEIT_ID_2)
-				.lastSyncTimestamp(Instant.now().minusSeconds(30000).toEpochMilli())
+				.lastSyncTimestamp(OrganisationsEinheitTestFactory.LAST_SYNC_UPDATE - 2)
 				.build();
 		private final OrganisationsEinheit synced1 = OrganisationsEinheitTestFactory.createBuilder()
 				.id(null)
@@ -236,7 +236,8 @@ class OrganisationsEinheitRepositoryITCase {
 		void shouldFindAllWithoutSyncResult() {
 			var allWithoutSyncResult = repository.findAllWithoutSyncResult();
 
-			assertThat(allWithoutSyncResult).extracting(OrganisationsEinheit::getId).containsExactlyInAnyOrder(WITHOUT_SYNC_RESULT_ID_1, WITHOUT_SYNC_RESULT_ID_2);
+			assertThat(allWithoutSyncResult).extracting(OrganisationsEinheit::getId)
+					.containsExactlyInAnyOrder(WITHOUT_SYNC_RESULT_ID_1, WITHOUT_SYNC_RESULT_ID_2);
 		}
 	}
 
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitServiceTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitServiceTest.java
index 822efd5c057a8b196deac785e1563848070d67c8..aaf92457a1ca0d94efb929733852e1dbf022b03b 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitServiceTest.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitServiceTest.java
@@ -139,12 +139,26 @@ class OrganisationsEinheitServiceTest {
 	@Nested
 	class TestGetChildren {
 
+		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
+
+		@BeforeEach
+		void setUp() {
+			when(repository.findChildren(OrganisationsEinheitTestFactory.ID)).thenReturn(List.of(organisationsEinheit));
+		}
+
 		@Test
 		void shouldCallRepository() {
 			service.getChildren(OrganisationsEinheitTestFactory.ID);
 
 			verify(repository).findChildren(OrganisationsEinheitTestFactory.ID);
 		}
+
+		@Test
+		void shouldReturnChildren() {
+			var children = service.getChildren(OrganisationsEinheitTestFactory.ID);
+
+			assertThat(children).containsExactly(organisationsEinheit);
+		}
 	}
 
 	@Nested
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitSettingsTestFactory.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitSettingsTestFactory.java
index ababf88ba11eb1378cc4416c357098c48abd8bc7..c5028fb0e25bb8b6127e623a4e09b75794545d61 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitSettingsTestFactory.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitSettingsTestFactory.java
@@ -15,4 +15,9 @@ public class OrganisationsEinheitSettingsTestFactory {
 				.signatur(SIGNATUR);
 	}
 
+	public static OrganisationsEinheitSettings.OrganisationsEinheitSettingsBuilder createNewBuilder() {
+		return OrganisationsEinheitSettings.builder()
+				.signatur(LoremIpsum.getInstance().getWords(3));
+	}
+
 }
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitTestFactory.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitTestFactory.java
index 2feb3311fb010748e58beed1f48b9a132c24d015..756ec38fc6a01660b352924cebbd24176c4a9939 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitTestFactory.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitTestFactory.java
@@ -34,4 +34,16 @@ public class OrganisationsEinheitTestFactory {
 				.lastSyncTimestamp(LAST_SYNC_UPDATE);
 	}
 
+	public static OrganisationsEinheit.OrganisationsEinheitBuilder createNewBuilder() {
+		return OrganisationsEinheit.builder()
+				.id(UUID.randomUUID().toString())
+				.keycloakId(UUID.randomUUID().toString())
+				.name(LoremIpsum.getInstance().getName())
+				.organisationsEinheitId(UUID.randomUUID().toString())
+				.parentId(UUID.randomUUID().toString())
+				.zufiId(UUID.randomUUID().toString())
+				.syncResult(SyncResult.DELETED)
+				.settings(OrganisationsEinheitSettingsTestFactory.createNewBuilder().build())
+				.lastSyncTimestamp(LAST_SYNC_UPDATE - 10000);
+	}
 }
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncAddedOrganisationsEinheitenITCase.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncAddedOrganisationsEinheitenITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..1af0cf1617c485ebb64936aba8e653cdafa83ed1
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncAddedOrganisationsEinheitenITCase.java
@@ -0,0 +1,62 @@
+package de.ozgcloud.admin.organisationseinheit;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.assertj.core.groups.Tuple.tuple;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.UUID;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.test.context.ContextConfiguration;
+
+import de.ozgcloud.admin.common.KeycloakInitializer;
+import de.ozgcloud.admin.keycloak.Group;
+import de.ozgcloud.admin.keycloak.KeycloakRemoteService;
+import de.ozgcloud.common.test.DbInitializer;
+import de.ozgcloud.common.test.ITCase;
+
+@ITCase
+@ContextConfiguration(initializers = { DbInitializer.class, KeycloakInitializer.class })
+class SyncAddedOrganisationsEinheitenITCase {
+
+	@Autowired
+	private SyncService service;
+	@SpyBean
+	private KeycloakRemoteService keycloakRemoteService;
+	@Autowired
+	private MongoOperations operations;
+
+	private final long syncTimestamp = Instant.now().toEpochMilli();
+
+	@BeforeEach
+	void clearDatabase() {
+		operations.dropCollection(OrganisationsEinheit.class);
+	}
+
+	@Test
+	void shouldSynchronizeAddedTopLevelGroup() {
+		var topLevel = topLevel("shouldSynchronizeAddedTopLevelGroup");
+		operations.save(topLevel);
+
+		service.syncAddedOrganisationsEinheiten(syncTimestamp);
+
+		assertThat(keycloakRemoteService.getGroupsWithOrganisationsEinheitId())
+				.extracting(Group::getName, Group::getOrganisationsEinheitId, Group::getSubGroups)
+				.contains(tuple(topLevel.getName(), topLevel.getOrganisationsEinheitId(), List.of()));
+	}
+
+	private static OrganisationsEinheit topLevel(String nameSuffix) {
+		return OrganisationsEinheitTestFactory.createBuilder()
+				.id(UUID.randomUUID().toString())
+				.parentId(null)
+				.keycloakId(null)
+				.syncResult(null)
+				.name("topLevel (%s)".formatted(nameSuffix))
+				.build();
+	}
+}
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncServiceITCase.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..c681785b71ea74380ac446ca736527d131579284
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncServiceITCase.java
@@ -0,0 +1,630 @@
+package de.ozgcloud.admin.organisationseinheit;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.time.Instant;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.data.mongodb.core.MongoOperations;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.admin.keycloak.GroupTestFactory;
+import de.ozgcloud.admin.keycloak.KeycloakRemoteService;
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+@EnableAutoConfiguration
+class SyncServiceITCase {
+
+	@Autowired
+	private MongoOperations operations;
+
+	@Autowired
+	private SyncService service;
+
+	@Autowired
+	private OrganisationsEinheitRepository repository;
+
+	@MockBean
+	private KeycloakRemoteService keycloakRemoteService;
+
+	@MockBean
+	private OrganisationsEinheitRemoteService organisationsEinheitRemoteService;
+
+	@BeforeEach
+	void clearDatabase() {
+		operations.dropCollection(OrganisationsEinheit.class);
+	}
+
+	@DisplayName("Organisationseinheit not found in PVOG")
+	@Test
+	void shouldSyncNotFoundInPvog() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().clearSubGroups().build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(List.of());
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+
+		var synced = repository.findAll();
+
+		assertThat(synced).
+				hasSize(1)
+				.first()
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.NOT_FOUND_IN_PVOG,
+						null,
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("Organisationseinheit found in PVOG but group name is different")
+	@Test
+	void shouldSyncNameMismatch() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().clearSubGroups().build();
+		var pvogOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+
+		var synced = repository.findAll();
+
+		assertThat(synced).
+				hasSize(1)
+				.first()
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						pvogOranigastionsEinheit.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.NAME_MISMATCH,
+						pvogOranigastionsEinheit.getId(),
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("Multiple Organisationseinheiten for same group found in PVOG")
+	@Test
+	void shouldSyncOrganisationsEinheitNotUnique() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().clearSubGroups().build();
+		var pvogOranigastionsEinheit1 = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.build();
+		var pvogOranigastionsEinheit2 = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit1, pvogOranigastionsEinheit2));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+
+		var synced = repository.findAll();
+
+		assertThat(synced).
+				hasSize(1)
+				.first()
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.ORGANISATIONSEINHEIT_ID_NOT_UNIQUE,
+						null,
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("Organisationseinheit found in PVOG and have same data")
+	@Test
+	void shouldSyncOk() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().clearSubGroups().build();
+		var pvogOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.name(group.getName()).build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+
+		var synced = repository.findAll();
+
+		assertThat(synced).
+				hasSize(1)
+				.first()
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.OK,
+						pvogOranigastionsEinheit.getId(),
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("OrganisationseinheitId attribute of group changed")
+	@Test
+	void shouldSyncUpdateAttribute() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().clearSubGroups().build();
+		var pvogOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.name(group.getName()).build();
+		var newOrganisationsEinheitId = UUID.randomUUID().toString();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(
+				Stream.of(group.toBuilder().organisationsEinheitId(newOrganisationsEinheitId).build()));
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp + 1000);
+
+		var synced = repository.findAll();
+
+		assertThat(synced).
+				hasSize(1)
+				.first()
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						newOrganisationsEinheitId,
+						SyncResult.NOT_FOUND_IN_PVOG,
+						null,
+						null,
+						Collections.emptyList(),
+						syncTimestamp + 1000);
+	}
+
+	@DisplayName("Group deleted in Keycloak")
+	@Test
+	void shouldSyncDeleted() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().clearSubGroups().build();
+		var pvogOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.name(group.getName()).build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of());
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp + 1000);
+
+		var synced = repository.findAll();
+
+		assertThat(synced).
+				hasSize(1)
+				.first()
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.DELETED,
+						pvogOranigastionsEinheit.getId(),
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("Organisationseinheit for parent group and sub group not found in PVOG")
+	@Test
+	void shouldSyncParentNotFoundInPvogSubGroupNotFoundInPvog() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().build();
+		var subGroup = group.getSubGroups().getFirst();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(List.of());
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+
+		var parentSynced = repository.findSyncedByKeycloakId(group.getId()).get();
+		var childSynced = repository.findSyncedByKeycloakId(subGroup.getId()).get();
+
+		assertThat(parentSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.NOT_FOUND_IN_PVOG,
+						null,
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+		assertThat(childSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						subGroup.getId(),
+						subGroup.getName(),
+						subGroup.getOrganisationsEinheitId(),
+						SyncResult.NOT_FOUND_IN_PVOG,
+						null,
+						parentSynced.getId(),
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("Organisationseinheit for parent group and sub group found in PVOG but have different names")
+	@Test
+	void shouldSyncParentNameMismatchSubGroupNameMismatch() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().build();
+		var subGroup = group.getSubGroups().getFirst();
+		var pvogOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.build();
+		var pvogChildOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder()
+				.organisationsEinheitId(subGroup.getOrganisationsEinheitId()).name(
+						LoremIpsum.getInstance().getWords(2))
+				.build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.SUB_GROUP_ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogChildOranigastionsEinheit));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+
+		var parentSynced = repository.findSyncedByKeycloakId(group.getId()).get();
+		var childSynced = repository.findSyncedByKeycloakId(subGroup.getId()).get();
+
+		assertThat(parentSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						pvogOranigastionsEinheit.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.NAME_MISMATCH,
+						pvogOranigastionsEinheit.getId(),
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+		assertThat(childSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						subGroup.getId(),
+						pvogChildOranigastionsEinheit.getName(),
+						subGroup.getOrganisationsEinheitId(),
+						SyncResult.NAME_MISMATCH,
+						pvogChildOranigastionsEinheit.getId(),
+						parentSynced.getId(),
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("Multiple Organisationseinheiten for parent group and sub group found in PVOG")
+	@Test
+	void shouldSyncParentAndChildOrganisationsEinheitNotUnique() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().build();
+		var subGroup = group.getSubGroups().getFirst();
+		var pvogOranigastionsEinheit1 = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.build();
+		var pvogOranigastionsEinheit2 = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.build();
+		var pvogChildOranigastionsEinheit1 = OrganisationsEinheitTestFactory.createBuilder()
+				.organisationsEinheitId(subGroup.getOrganisationsEinheitId()).name(
+						LoremIpsum.getInstance().getWords(2))
+				.build();
+		var pvogChildOranigastionsEinheit2 = OrganisationsEinheitTestFactory.createBuilder()
+				.organisationsEinheitId(subGroup.getOrganisationsEinheitId()).name(
+						LoremIpsum.getInstance().getWords(2))
+				.build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit1, pvogOranigastionsEinheit2));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.SUB_GROUP_ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogChildOranigastionsEinheit1, pvogChildOranigastionsEinheit2));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+
+		var parentSynced = repository.findSyncedByKeycloakId(group.getId()).get();
+		var childSynced = repository.findSyncedByKeycloakId(subGroup.getId()).get();
+
+		assertThat(parentSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.ORGANISATIONSEINHEIT_ID_NOT_UNIQUE,
+						null,
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+		assertThat(childSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						subGroup.getId(),
+						subGroup.getName(),
+						subGroup.getOrganisationsEinheitId(),
+						SyncResult.ORGANISATIONSEINHEIT_ID_NOT_UNIQUE,
+						null,
+						parentSynced.getId(),
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("Organisationseinheit and child Organisationseinheit found in PVOG and have same data")
+	@Test
+	void shouldSyncOkGroupWithSubGroup() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().build();
+		var subGroup = group.getSubGroups().getFirst();
+		var pvogOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.name(group.getName()).build();
+		var pvogChildOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder()
+				.organisationsEinheitId(subGroup.getOrganisationsEinheitId()).name(
+						subGroup.getName())
+				.build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.SUB_GROUP_ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogChildOranigastionsEinheit));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+
+		var parentSynced = repository.findSyncedByKeycloakId(group.getId()).get();
+		var childSynced = repository.findSyncedByKeycloakId(subGroup.getId()).get();
+
+		assertThat(parentSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.OK,
+						pvogOranigastionsEinheit.getId(),
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+		assertThat(childSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						subGroup.getId(),
+						subGroup.getName(),
+						subGroup.getOrganisationsEinheitId(),
+						SyncResult.OK,
+						pvogChildOranigastionsEinheit.getId(),
+						parentSynced.getId(),
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+	@DisplayName("Group with sub group deleted in Keycloak")
+	@Test
+	void shouldSyncGroupAndSubGroupDeleted() {
+		var syncTimestamp = Instant.now().toEpochMilli();
+		var group = GroupTestFactory.createBuilder().build();
+		var subGroup = group.getSubGroups().getFirst();
+		var pvogOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder().organisationsEinheitId(group.getOrganisationsEinheitId())
+				.name(group.getName()).build();
+		var pvogChildOranigastionsEinheit = OrganisationsEinheitTestFactory.createBuilder()
+				.organisationsEinheitId(subGroup.getOrganisationsEinheitId()).name(
+						subGroup.getName())
+				.build();
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogOranigastionsEinheit));
+		when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.SUB_GROUP_ORGANISATIONS_EINHEIT_ID)).thenReturn(
+				List.of(pvogChildOranigastionsEinheit));
+
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp);
+		when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of());
+		service.syncOrganisationsEinheitenFromKeycloak(syncTimestamp + 1000);
+
+		var parentSynced = repository.findSyncedByKeycloakId(group.getId()).get();
+		var childSynced = repository.findSyncedByKeycloakId(subGroup.getId()).get();
+
+		assertThat(parentSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						group.getId(),
+						group.getName(),
+						group.getOrganisationsEinheitId(),
+						SyncResult.DELETED,
+						pvogOranigastionsEinheit.getId(),
+						null,
+						Collections.emptyList(),
+						syncTimestamp);
+		assertThat(childSynced)
+				.matches(organisationsEinheit -> Objects.nonNull(organisationsEinheit.getId()))
+				.matches(organisationsEinheit -> Objects.isNull(organisationsEinheit.getSettings().getSignatur()))
+				.extracting(
+						OrganisationsEinheit::getKeycloakId,
+						OrganisationsEinheit::getName,
+						OrganisationsEinheit::getOrganisationsEinheitId,
+						OrganisationsEinheit::getSyncResult,
+						OrganisationsEinheit::getZufiId,
+						OrganisationsEinheit::getParentId,
+						OrganisationsEinheit::getChildren,
+						OrganisationsEinheit::getLastSyncTimestamp
+				).containsExactly(
+						subGroup.getId(),
+						subGroup.getName(),
+						subGroup.getOrganisationsEinheitId(),
+						SyncResult.DELETED,
+						pvogChildOranigastionsEinheit.getId(),
+						parentSynced.getId(),
+						Collections.emptyList(),
+						syncTimestamp);
+	}
+
+}
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncServiceTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncServiceTest.java
index 401216f163eb0aadda47be61874496c5ccd57ba8..f9b3a0011fc4767b653a49ea3d1c3b85f65034e8 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncServiceTest.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/SyncServiceTest.java
@@ -20,6 +20,8 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.admin.keycloak.AddGroupData;
 import de.ozgcloud.admin.keycloak.AddGroupDataTestFactory;
 import de.ozgcloud.admin.keycloak.Group;
@@ -54,7 +56,7 @@ class SyncServiceTest {
 		@BeforeEach
 		void setUp() {
 			when(keycloakRemoteService.getGroupsWithOrganisationsEinheitId()).thenReturn(Stream.of(group));
-			doNothing().when(service).syncGroups(any(), any(), anyLong());
+			doNothing().when(service).syncGroupsWithSubGroups(any(), any(), anyLong());
 		}
 
 		@Test
@@ -68,7 +70,7 @@ class SyncServiceTest {
 		void shouldSyncGroupsFromKeycloak() {
 			callService();
 
-			verify(service).syncGroups(group, null, syncTimestamp);
+			verify(service).syncGroupsWithSubGroups(group, null, syncTimestamp);
 		}
 
 		@Test
@@ -85,7 +87,7 @@ class SyncServiceTest {
 	}
 
 	@Nested
-	class TestSyncGroups {
+	class TestSyncGroupsWithSubGroups {
 
 		private final long syncTimestamp = Instant.now().toEpochMilli();
 		private final Group group = GroupTestFactory.create();
@@ -96,28 +98,28 @@ class SyncServiceTest {
 		@BeforeEach
 		void setUp() {
 			doReturn(syncedOrganisationsEinheitGroup).when(service).syncGroup(group, null, syncTimestamp);
-			doReturn(savedOrganisationsEinheitGroup).when(service).saveSyncedOrganisationsEinheit(any());
+			doReturn(savedOrganisationsEinheitGroup).when(service).saveSyncedOrganisationsEinheit(syncedOrganisationsEinheitGroup);
 		}
 
 		@Test
 		void shouldSyncGroup() {
-			service.syncGroups(group, null, syncTimestamp);
+			service.syncGroupsWithSubGroups(group, null, syncTimestamp);
 
 			verify(service).syncGroup(group, null, syncTimestamp);
 		}
 
 		@Test
-		void shouldSaveSyncedGroup() {
-			service.syncGroups(group, null, syncTimestamp);
+		void shouldSaveSyncedOrganisationsEinheit() {
+			service.syncGroupsWithSubGroups(group, null, syncTimestamp);
 
 			verify(service).saveSyncedOrganisationsEinheit(syncedOrganisationsEinheitGroup);
 		}
 
 		@Test
 		void shouldSyncSubGroupsWithSyncedOrganisationsEinheitAsParent() {
-			service.syncGroups(group, null, syncTimestamp);
+			service.syncGroupsWithSubGroups(group, null, syncTimestamp);
 
-			verify(service).syncGroups(group.getSubGroups().getFirst(), savedOrganisationsEinheitGroup, syncTimestamp);
+			verify(service).syncGroupsWithSubGroups(group.getSubGroups().getFirst(), savedOrganisationsEinheitGroup, syncTimestamp);
 		}
 	}
 
@@ -129,14 +131,18 @@ class SyncServiceTest {
 		private final OrganisationsEinheit parent = OrganisationsEinheitTestFactory.createBuilder().id(UUID.randomUUID().toString()).build();
 		private final OrganisationsEinheit pvogOrganisationsEinheit = OrganisationsEinheitTestFactory.createBuilder().zufiId(null).settings(null)
 				.parentId(null).syncResult(null).build();
+		private final String syncedName = LoremIpsum.getInstance().getWords(3);
+		private final SyncResult syncedSyncResult = SyncResult.OK;
+		private final String syncedZufiId = UUID.randomUUID().toString();
 
 		@Nested
 		class ParentGroup {
 
 			@BeforeEach
 			void setUp() {
-				doReturn(OrganisationsEinheitTestFactory.NAME).when(service).syncName(anyList(), any());
-				doReturn(SyncResult.OK).when(service).evaluateSyncResult(anyList(), any());
+				doReturn(syncedName).when(service).syncName(List.of(pvogOrganisationsEinheit), group);
+				doReturn(syncedSyncResult).when(service).evaluateSyncResult(List.of(pvogOrganisationsEinheit), group);
+				doReturn(syncedZufiId).when(service).syncZufiId(List.of(pvogOrganisationsEinheit));
 				when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID)).thenReturn(
 						List.of(pvogOrganisationsEinheit));
 			}
@@ -150,16 +156,18 @@ class SyncServiceTest {
 
 			@Test
 			void shouldSyncName() {
-				service.syncGroup(group, null, syncTimestamp);
+				var synced = service.syncGroup(group, null, syncTimestamp);
 
 				verify(service).syncName(List.of(pvogOrganisationsEinheit), group);
+				assertThat(synced.getName()).isEqualTo(syncedName);
 			}
 
 			@Test
 			void shouldEvaluateSyncResult() {
-				service.syncGroup(group, null, syncTimestamp);
+				var synced = service.syncGroup(group, null, syncTimestamp);
 
 				verify(service).evaluateSyncResult(List.of(pvogOrganisationsEinheit), group);
+				assertThat(synced.getSyncResult()).isEqualTo(syncedSyncResult);
 			}
 
 			@Test
@@ -169,11 +177,19 @@ class SyncServiceTest {
 				verify(organisationsEinheitRemoteService).getByOrganisationsEinheitId(GroupTestFactory.ORGANISATIONS_EINHEIT_ID);
 			}
 
+			@Test
+			void shouldSetOrganisationsEinheitId() {
+				var synced = service.syncGroup(group, null, syncTimestamp);
+
+				assertThat(synced.getOrganisationsEinheitId()).isEqualTo(group.getOrganisationsEinheitId());
+			}
+
 			@Test
 			void shouldSyncZufiId() {
-				service.syncGroup(group, null, syncTimestamp);
+				var synced = service.syncGroup(group, null, syncTimestamp);
 
 				verify(service).syncZufiId(List.of(pvogOrganisationsEinheit));
+				assertThat(synced.getZufiId()).isEqualTo(syncedZufiId);
 			}
 
 			@Test
@@ -189,8 +205,9 @@ class SyncServiceTest {
 
 			@BeforeEach
 			void setUp() {
-				doReturn(OrganisationsEinheitTestFactory.NAME).when(service).syncName(anyList(), any());
-				doReturn(SyncResult.OK).when(service).evaluateSyncResult(anyList(), any());
+				doReturn(syncedName).when(service).syncName(List.of(pvogOrganisationsEinheit), group.getSubGroups().getFirst());
+				doReturn(syncedSyncResult).when(service).evaluateSyncResult(List.of(pvogOrganisationsEinheit), group.getSubGroups().getFirst());
+				doReturn(syncedZufiId).when(service).syncZufiId(List.of(pvogOrganisationsEinheit));
 				when(organisationsEinheitRemoteService.getByOrganisationsEinheitId(GroupTestFactory.SUB_GROUP_ORGANISATIONS_EINHEIT_ID)).thenReturn(
 						List.of(pvogOrganisationsEinheit));
 			}
@@ -204,23 +221,26 @@ class SyncServiceTest {
 
 			@Test
 			void shouldSyncName() {
-				service.syncGroup(group.getSubGroups().getFirst(), parent, syncTimestamp);
+				var synced = service.syncGroup(group.getSubGroups().getFirst(), parent, syncTimestamp);
 
 				verify(service).syncName(List.of(pvogOrganisationsEinheit), group.getSubGroups().getFirst());
+				assertThat(synced.getName()).isEqualTo(syncedName);
 			}
 
 			@Test
 			void shouldEvaluateSyncResult() {
-				service.syncGroup(group.getSubGroups().getFirst(), parent, syncTimestamp);
+				var synced = service.syncGroup(group.getSubGroups().getFirst(), parent, syncTimestamp);
 
 				verify(service).evaluateSyncResult(List.of(pvogOrganisationsEinheit), group.getSubGroups().getFirst());
+				assertThat(synced.getSyncResult()).isEqualTo(syncedSyncResult);
 			}
 
 			@Test
 			void shouldGetOrganisationsEinheit() {
-				service.syncGroup(group.getSubGroups().getFirst(), parent, syncTimestamp);
+				var synced = service.syncGroup(group.getSubGroups().getFirst(), parent, syncTimestamp);
 
 				verify(organisationsEinheitRemoteService).getByOrganisationsEinheitId(GroupTestFactory.SUB_GROUP_ORGANISATIONS_EINHEIT_ID);
+				assertThat(synced.getOrganisationsEinheitId()).isEqualTo(group.getSubGroups().getFirst().getOrganisationsEinheitId());
 			}
 
 			@Test
@@ -232,9 +252,10 @@ class SyncServiceTest {
 
 			@Test
 			void shouldSyncZufiId() {
-				service.syncGroup(group.getSubGroups().getFirst(), parent, syncTimestamp);
+				var synced = service.syncGroup(group.getSubGroups().getFirst(), parent, syncTimestamp);
 
 				verify(service).syncZufiId(List.of(pvogOrganisationsEinheit));
+				assertThat(synced.getZufiId()).isEqualTo(syncedZufiId);
 			}
 
 			@Test
@@ -377,7 +398,7 @@ class SyncServiceTest {
 		@Nested
 		class SyncedOrganisationsEinheitExists {
 
-			private final OrganisationsEinheit existingOrganisationsEinheit = OrganisationsEinheitTestFactory.create();
+			private final OrganisationsEinheit existingOrganisationsEinheit = OrganisationsEinheitTestFactory.createNewBuilder().build();
 
 			@Captor
 			private ArgumentCaptor<OrganisationsEinheit> savedOrganisationsEinheitArgumentCaptor;
@@ -416,16 +437,20 @@ class SyncServiceTest {
 	}
 
 	@Nested
-	class TestsyncAddedOrganisationsEinheiten {
+	class TestSyncAddedOrganisationsEinheiten {
 
 		private final long syncTimestamp = Instant.now().toEpochMilli();
 		private final OrganisationsEinheit withoutSyncResult1 = OrganisationsEinheitTestFactory.createBuilder().id("A").build();
 		private final OrganisationsEinheit withoutSyncResult2 = OrganisationsEinheitTestFactory.createBuilder().id("B").build();
+		private final OrganisationsEinheit[] organisationsEinheiten = new OrganisationsEinheit[] { withoutSyncResult2, withoutSyncResult1 };
+
+		@Captor
+		private ArgumentCaptor<Stream<OrganisationsEinheit>> streamArgumentCaptor;
 
 		@BeforeEach
 		void setUp() {
-			when(repository.findAllWithoutSyncResult()).thenReturn(Stream.of(withoutSyncResult1, withoutSyncResult2));
-			doNothing().when(service).syncAddedOrganisationsEinheit(anyLong(), any());
+			when(repository.findAllWithoutSyncResult()).thenReturn(Stream.of(organisationsEinheiten));
+			doNothing().when(service).syncAddedOrganisationsEinheit(any(), anyLong());
 		}
 
 		@Test
@@ -439,14 +464,14 @@ class SyncServiceTest {
 		void shouldSynchronizeFirstOrganisationsEinheit() {
 			callService();
 
-			verify(service).syncAddedOrganisationsEinheit(syncTimestamp, withoutSyncResult1);
+			verify(service).syncAddedOrganisationsEinheit(withoutSyncResult1, syncTimestamp);
 		}
 
 		@Test
 		void shouldSynchronizeSecondOrganisationsEinheit() {
 			callService();
 
-			verify(service).syncAddedOrganisationsEinheit(syncTimestamp, withoutSyncResult2);
+			verify(service).syncAddedOrganisationsEinheit(withoutSyncResult2, syncTimestamp);
 		}
 
 		private void callService() {
@@ -458,75 +483,128 @@ class SyncServiceTest {
 	class TestSyncAddedOrganisationsEinheit {
 
 		private final long syncTimestamp = Instant.now().toEpochMilli();
+		private final String addedGroupId = UUID.randomUUID().toString();
 		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
-		private final AddGroupData addGroupData = AddGroupDataTestFactory.create();
-		private final String keycloakId = GroupTestFactory.ID;
-
-		@Captor
-		private ArgumentCaptor<OrganisationsEinheit> savedOrganisationsEinheitArgumentCaptor;
-
-		@BeforeEach
-		void setUp() {
-			when(organisationsEinheitMapper.toAddGroupData(organisationsEinheit)).thenReturn(addGroupData);
-		}
 
 		@Test
-		void shouldCreateAddGroupData() {
-			givenAddGroupInKeycloakSuccessful();
+		void shouldAddAsGroupInKeycloak() {
+			doReturn(Optional.empty()).when(service).addAsGroupInKeycloak(organisationsEinheit);
 
 			callService();
 
-			verify(organisationsEinheitMapper).toAddGroupData(organisationsEinheit);
+			verify(service).addAsGroupInKeycloak(organisationsEinheit);
 		}
 
 		@Test
-		void shouldAddGroupInKeycloak() {
-			givenAddGroupInKeycloakSuccessful();
+		void shouldUpdateAfterSuccessfulGroupCreation() {
+			doReturn(Optional.of(addedGroupId)).when(service).addAsGroupInKeycloak(organisationsEinheit);
+			doNothing().when(service).updateAfterSuccessfulGroupCreation(organisationsEinheit, addedGroupId, syncTimestamp);
 
 			callService();
 
-			verify(service).addGroupInKeycloak(addGroupData);
+			verify(service).updateAfterSuccessfulGroupCreation(organisationsEinheit, addedGroupId, syncTimestamp);
 		}
 
 		@Test
-		void shouldSaveIfAddGroupSuccessful() {
-			givenAddGroupInKeycloakSuccessful();
+		void shouldNotUpdate() {
+			doReturn(Optional.empty()).when(service).addAsGroupInKeycloak(organisationsEinheit);
 
 			callService();
 
-			verify(repository).save(savedOrganisationsEinheitArgumentCaptor.capture());
-			assertThat(savedOrganisationsEinheitArgumentCaptor.getValue()).extracting(
-					OrganisationsEinheit::getKeycloakId,
-					OrganisationsEinheit::getSyncResult,
-					OrganisationsEinheit::getLastSyncTimestamp
-			).containsExactly(keycloakId, SyncResult.OK, syncTimestamp);
+			verify(service, never()).updateAfterSuccessfulGroupCreation(any(), any(), anyLong());
 		}
 
-		@Test
-		void shouldNotSaveIfAddGroupFailed() {
-			givenAddGroupInKeycloakFailed();
+		private void callService() {
+			service.syncAddedOrganisationsEinheit(organisationsEinheit, syncTimestamp);
+		}
+	}
 
-			callService();
+	@Nested
+	class TestAddAsGroupInKeycloak {
 
-			verifyNoInteractions(repository);
-		}
+		@Nested
+		class OnParentIdIsNotSet {
+
+			private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.createBuilder().parentId(null).build();
+			private final AddGroupData addGroupData = AddGroupDataTestFactory.create();
+			private final String addedGroupId = UUID.randomUUID().toString();
 
-		private void givenAddGroupInKeycloakSuccessful() {
-			doReturn(Optional.of(keycloakId)).when(service).addGroupInKeycloak(addGroupData);
+			@BeforeEach
+			void init() {
+				when(organisationsEinheitMapper.toAddGroupData(organisationsEinheit)).thenReturn(addGroupData);
+				doReturn(Optional.of(addedGroupId)).when(service).addGroupInKeycloak(addGroupData);
+			}
+
+			@Test
+			void shouldCreateAddGroupData() {
+				callService();
+
+				verify(organisationsEinheitMapper).toAddGroupData(organisationsEinheit);
+			}
+
+			@Test
+			void shouldAddGroupInKeycloak() {
+				callService();
+
+				verify(service).addGroupInKeycloak(addGroupData);
+			}
+
+			@Test
+			void shouldReturnAddedGroupId() {
+				var returnedGroupId = callService();
+
+				assertThat(returnedGroupId).get().isEqualTo(addedGroupId);
+			}
+
+			private Optional<String> callService() {
+				return service.addAsGroupInKeycloak(organisationsEinheit);
+			}
 		}
 
-		private void givenAddGroupInKeycloakFailed() {
-			doReturn(Optional.empty()).when(service).addGroupInKeycloak(addGroupData);
+		@Nested
+		class OnParentIdIsSet {
+
+			@Test
+			void shouldThrowException() {
+				var withParentId = OrganisationsEinheitTestFactory.create();
+				assertThatExceptionOfType(OrganisationsEinheitSynchronizationException.class)
+						.isThrownBy(() -> service.addAsGroupInKeycloak(withParentId))
+						.withMessage("Organisationseinheit " + withParentId.getOrganisationsEinheitId() + " has parent");
+			}
 		}
+	}
 
-		private void callService() {
-			service.syncAddedOrganisationsEinheit(syncTimestamp, organisationsEinheit);
+	@Nested
+	class TestUpdateAfterSuccessfulGroupCreation {
+
+		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.createBuilder()
+				.keycloakId(null)
+				.syncResult(null)
+				.lastSyncTimestamp(null)
+				.build();
+		private final long syncTimestamp = Instant.now().toEpochMilli();
+		private final String keycloakId = UUID.randomUUID().toString();
+
+		@Captor
+		private ArgumentCaptor<OrganisationsEinheit> organisationsEinheitArgumentCaptor;
+
+		@Test
+		void shouldSaveUpdatedOrganisationsEinheit() {
+			service.updateAfterSuccessfulGroupCreation(organisationsEinheit, keycloakId, syncTimestamp);
+
+			verify(repository).save(organisationsEinheitArgumentCaptor.capture());
+			assertThat(organisationsEinheitArgumentCaptor.getValue())
+					.extracting(OrganisationsEinheit::getKeycloakId, OrganisationsEinheit::getSyncResult, OrganisationsEinheit::getLastSyncTimestamp)
+					.containsExactly(keycloakId, SyncResult.OK, syncTimestamp);
 		}
 	}
 
 	@Nested
 	class TestAddGroupInKeycloak {
 
+		private static final String FAILURE_MESSAGE = LoremIpsum.getInstance().getWords(5);
+		private final Throwable resourceCreationException = new ResourceCreationException(FAILURE_MESSAGE);
+
 		private final String keycloakId = GroupTestFactory.ID;
 		private final AddGroupData addGroupData = AddGroupDataTestFactory.create();
 
@@ -549,12 +627,11 @@ class SyncServiceTest {
 		}
 
 		@Test
-		void shouldReturnEmptyInCaseOfException() {
+		void shouldThrowExceptionInCaseOfResourceCreationException() {
 			givenAddGroupFailed();
 
-			var keycloakId = callService();
-
-			assertThat(keycloakId).isEmpty();
+			assertThatExceptionOfType(OrganisationsEinheitSynchronizationException.class).isThrownBy(this::callService)
+					.withMessage("Error creating group %s in Keycloak", addGroupData.toString()).withCause(resourceCreationException);
 		}
 
 		private void givenAddGroupSuccessful() {
@@ -562,7 +639,7 @@ class SyncServiceTest {
 		}
 
 		private void givenAddGroupFailed() {
-			when(keycloakRemoteService.addGroup(addGroupData)).thenThrow(new ResourceCreationException("Failure"));
+			when(keycloakRemoteService.addGroup(addGroupData)).thenThrow(resourceCreationException);
 		}
 
 		private Optional<String> callService() {