diff --git a/bescheid-manager/pom.xml b/bescheid-manager/pom.xml
index 4da996d32dd21178fa46e1ccd3bd6efa1a786b1c..7e49b4339220cbfa22371a994b9ac6c1a037ef91 100644
--- a/bescheid-manager/pom.xml
+++ b/bescheid-manager/pom.xml
@@ -17,7 +17,8 @@
 	<properties>
 		<vorgang-manager.version>2.13.0</vorgang-manager.version>
 		<nachrichten-manager.version>2.9.0</nachrichten-manager.version>
-		<api-lib.version>0.11.0</api-lib.version>
+		<api-lib.version>0.12.0</api-lib.version>
+		<spring-cloud-config-client.version>4.1.3</spring-cloud-config-client.version>
 	</properties>
 
 	<dependencies>
@@ -96,6 +97,11 @@
 			<optional>true</optional>
 		</dependency>
 
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-config</artifactId>
+			<version>${spring-cloud-config-client.version}</version>
+		</dependency>
 
 		<dependency>
 			<groupId>com.fasterxml.jackson.datatype</groupId>
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java
index d181389e9cba0ebc0b7fa4f0ae3eecf9a1df3e3b..63f65d84733dae7ab98e63095234692c04f09dc7 100644
--- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java
@@ -10,7 +10,7 @@ import lombok.Builder;
 import lombok.Getter;
 import lombok.Singular;
 
-@Builder
+@Builder(toBuilder = true)
 @Getter
 public class Bescheid {
 
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java
index 6e6cdaf0d38f5e31d8ec32b6e6353ceb23b357ee..3beaadf3f4fd167bba8a29b34c613afe2348604c 100644
--- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java
@@ -106,7 +106,7 @@ class BescheidEventListener {
 	}
 
 	void doCreateBescheid(Command command) {
-		var createdItemId = attachedItemService.createBescheidDraft(command);
+		var createdItemId = service.createBescheidDraft(command);
 		eventPublisher.publishEvent(new BescheidCreatedEvent(command, createdItemId));
 	}
 
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidMapper.java
index 8abe425a3a1187b737bb41c851c1578a8db3e12c..28d4be14a789e33ff2b5b301c70341ad80f0b560 100644
--- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidMapper.java
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidMapper.java
@@ -1,9 +1,11 @@
 package de.ozgcloud.bescheid;
 
+import static de.ozgcloud.bescheid.Bescheid.*;
+
 import java.time.LocalDate;
-import java.time.ZonedDateTime;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -17,20 +19,27 @@ import org.mapstruct.Mapping;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 import org.mapstruct.ReportingPolicy;
+import org.springframework.beans.factory.annotation.Autowired;
 
-import de.ozgcloud.bescheid.Bescheid.SendBy;
-import de.ozgcloud.bescheid.Bescheid.Status;
 import de.ozgcloud.bescheid.vorgang.VorgangId;
+import de.ozgcloud.command.Command;
 import de.ozgcloud.common.attached_item.AttachedItem;
+import de.ozgcloud.common.attached_item.AttachedItemService;
 import de.ozgcloud.common.binaryfile.FileId;
+import de.ozgcloud.common.datatype.StringBasedValue;
 
 @Mapper(uses = { SentInfoMapper.class }, //
 		unmappedTargetPolicy = ReportingPolicy.WARN, //
 		collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, //
 		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
 		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) //
-public interface BescheidMapper {
+public abstract class BescheidMapper {
+
+	@Autowired
+	private SentInfoMapper sentInfoMapper;
 
+	@Mapping(target = "sentInfoOrBuilder", ignore = true)
+	@Mapping(target = "defaultInstanceForType", ignore = true)
 	@Mapping(target = "mergeFrom", ignore = true)
 	@Mapping(target = "clearField", ignore = true)
 	@Mapping(target = "clearOneof", ignore = true)
@@ -49,50 +58,118 @@ public interface BescheidMapper {
 	@Mapping(target = "nachrichtText", expression = "java(fromOptional(bescheid.getNachrichtText()))")
 	@Mapping(target = "nachrichtSubject", expression = "java(fromOptional(bescheid.getNachrichtSubject()))")
 	@Mapping(target = "attachmentsList", source = "attachments")
-	GrpcBescheid toBescheid(Bescheid bescheid);
+	abstract GrpcBescheid toBescheid(Bescheid bescheid);
 
-	default String toString(FileId fileId) {
+	String toString(FileId fileId) {
 		return fileId.toString();
 	}
 
-	default String toString(BescheidId bescheidId) {
+	String toString(BescheidId bescheidId) {
 		return bescheidId.toString();
 	}
 
-	default String fromOptional(Optional<String> optionalString) {
+	String fromOptional(Optional<String> optionalString) {
 		return optionalString.orElse(StringUtils.EMPTY);
 	}
 
-	default Bescheid mapFromAttachedItem(AttachedItem item) {
-		var itemMap = item.getItem();
-		var builder = Bescheid.builder()
+	@Mapping(target = "featuresOrBuilder", ignore = true)
+	@Mapping(target = "defaultInstanceForType", ignore = true)
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeFeatures", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "javaVersionBytes", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "versionBytes", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	abstract GrpcBescheidManagerConfigResponse fromBescheidManagerConfig(BescheidManagerConfig bescheidManagerConfig);
+
+	@Mapping(target = "defaultInstanceForType", ignore = true)
+	@Mapping(target = "bescheidOrBuilder", ignore = true)
+	@Mapping(target = "bescheid", ignore = true)
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeBescheid", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	abstract GrpcGetBescheidResponse toGetBescheidResponse(Bescheid bescheid);
+
+	@Mapping(target = "defaultInstanceForType", ignore = true)
+	@Mapping(target = "bescheidOrBuilder", ignore = true)
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeBescheid", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	abstract GrpcGetBescheidDraftResponse toGetBescheidDraftResponse(Bescheid bescheid);
+
+	Bescheid mapFromAttachedItem(AttachedItem item) {
+		return buildBescheidBuilder(item.getItem())
 				.id(BescheidId.from(item.getId()))
 				.version(item.getVersion())
 				.vorgangId(VorgangId.from(item.getVorgangId()))
-				.createdBy(UserId.from(MapUtils.getString(itemMap, Bescheid.FIELD_CREATED_BY)))
-				.bewilligt(MapUtils.getBoolean(itemMap, Bescheid.FIELD_BEWILLIGT))
-				.nachrichtText(Optional.ofNullable(MapUtils.getString(itemMap, Bescheid.FIELD_NACHRICHT_TEXT)))
-				.nachrichtSubject(Optional.ofNullable(MapUtils.getString(itemMap, Bescheid.FIELD_NACHRICHT_SUBJECT)))
-				.status(Status.valueOf(MapUtils.getString(itemMap, Bescheid.FIELD_STATUS)))
-				.beschiedenAm(LocalDate.parse(MapUtils.getString(itemMap, Bescheid.FIELD_BESCHIEDEN_AM)));
+				.build();
+	}
 
-		getBescheidDocument(itemMap).ifPresent(builder::bescheidDocument);
-		getAttachments(itemMap).ifPresent(builder::attachments);
-		getSendBy(itemMap).ifPresent(builder::sendBy);
-		getSentInfo(itemMap).ifPresent(builder::sentInfo);
+	Bescheid mapFromCommand(Command command) {
+		return buildBescheidBuilder(command.getBodyObject())
+				.vorgangId(VorgangId.from(command.getVorgangId()))
+				.build();
+	}
+
+	private Bescheid.BescheidBuilder buildBescheidBuilder(Map<String, Object> bescheidMap) {
+		var bescheidBuilder = Bescheid.builder();
+		Optional.ofNullable(MapUtils.getBoolean(bescheidMap, Bescheid.FIELD_BEWILLIGT)).ifPresent(bescheidBuilder::bewilligt);
+		getBeschiedenAm(bescheidMap).ifPresent(bescheidBuilder::beschiedenAm);
+		getStatus(bescheidMap).ifPresent(bescheidBuilder::status);
+		getCreatedBy(bescheidMap).ifPresent(bescheidBuilder::createdBy);
+		getBescheidDocument(bescheidMap).ifPresent(bescheidBuilder::bescheidDocument);
+		bescheidBuilder.nachrichtSubject(getNachrichtSubject(bescheidMap));
+		bescheidBuilder.nachrichtText(getNachrichtText(bescheidMap));
+		getSendBy(bescheidMap).ifPresent(bescheidBuilder::sendBy);
+		mapToAttachments(bescheidMap.get(Bescheid.FIELD_ATTACHMENTS)).ifPresent(bescheidBuilder::attachments);
+		getSentInfo(bescheidMap).ifPresent(bescheidBuilder::sentInfo);
+		return bescheidBuilder;
+	}
+
+	Optional<LocalDate> getBeschiedenAm(Map<String, Object> bescheidMap) {
+		return getStringValue(bescheidMap, Bescheid.FIELD_BESCHIEDEN_AM).map(LocalDate::parse);
+	}
+
+	Optional<Bescheid.Status> getStatus(Map<String, Object> bescheidMap) {
+		return getStringValue(bescheidMap, Bescheid.FIELD_STATUS).map(Bescheid.Status::valueOf);
+	}
+
+	Optional<UserId> getCreatedBy(Map<String, Object> bescheidMap) {
+		return getStringValue(bescheidMap, Bescheid.FIELD_CREATED_BY).map(UserId::from);
+	}
 
-		return builder.build();
+	Optional<SendBy> getSendBy(Map<String, Object> bescheidMap) {
+		return getStringValue(bescheidMap, Bescheid.FIELD_SEND_BY).map(SendBy::valueOf);
 	}
 
-	default Optional<FileId> getBescheidDocument(Map<String, Object> itemMap) {
-		return Optional.ofNullable(MapUtils.getString(itemMap, Bescheid.FIELD_BESCHEID_DOCUMENT)).map(FileId::from);
+	Optional<FileId> getBescheidDocument(Map<String, Object> bescheidMap) {
+		return getStringValue(bescheidMap, Bescheid.FIELD_BESCHEID_DOCUMENT).map(FileId::from);
 	}
 
-	default Optional<List<FileId>> getAttachments(Map<String, Object> itemMap) {
-		return mapToAttachments(MapUtils.getObject(itemMap, Bescheid.FIELD_ATTACHMENTS));
+	private Optional<String> getNachrichtSubject(Map<String, Object> bescheidMap) {
+		return getStringValue(bescheidMap, Bescheid.FIELD_NACHRICHT_SUBJECT);
 	}
 
-	default Optional<List<FileId>> mapToAttachments(Object attachments) {
+	private Optional<String> getNachrichtText(Map<String, Object> bescheidMap) {
+		return getStringValue(bescheidMap, Bescheid.FIELD_NACHRICHT_TEXT);
+	}
+
+	private Optional<String> getStringValue(Map<String, Object> srcMap, String field) {
+		return Optional.ofNullable(MapUtils.getString(srcMap, field)).map(StringUtils::trimToNull);
+	}
+
+	Optional<List<FileId>> mapToAttachments(Object attachments) {
 		if (Objects.isNull(attachments) || StringUtils.isEmpty(String.valueOf(attachments))) {
 			return Optional.empty();
 		}
@@ -102,47 +179,55 @@ public interface BescheidMapper {
 		return Optional.of(Collections.singletonList(FileId.from((String) attachments)));
 	}
 
-	default Optional<SendBy> getSendBy(Map<String, Object> itemMap) {
-		return Optional.ofNullable(MapUtils.getString(itemMap, Bescheid.FIELD_SEND_BY)).map(SendBy::valueOf);
+	private Optional<SentInfo> getSentInfo(Map<String, Object> itemMap) {
+		return Optional.ofNullable(MapUtils.getMap(itemMap, Bescheid.FIELD_SENT_INFO)).map(sentInfoMapper::toSentInfo);
 	}
 
-	default Optional<SentInfo> getSentInfo(Map<String, Object> itemMap) {
-		return Optional.ofNullable(MapUtils.getMap(itemMap, Bescheid.FIELD_SENT_INFO)).map(this::toSentInfo);
+	@Mapping(target = "client", constant = BescheidCallContextAttachingInterceptor.BESCHEID_MANAGER_CLIENT_NAME)
+	@Mapping(target = "itemName", constant = AttachedItemService.BESCHEID_ITEM_NAME)
+	@Mapping(target = "item", expression = "java(mapToItem(bescheid))")
+	public abstract AttachedItem mapFromBescheid(Bescheid bescheid);
+
+	String mapToString(StringBasedValue value) {
+		return value.toString();
 	}
 
-	default SentInfo toSentInfo(Map<String, Object> sentInfoMap) {
-		return SentInfo.builder()
-				.sentBy(MapUtils.getString(sentInfoMap, SentInfo.FIELD_SENT_BY))
-				.sentAt(ZonedDateTime.parse(MapUtils.getString(sentInfoMap, SentInfo.FIELD_SENT_AT)))
-				.build();
+	public Map<String, Object> mapToItem(Bescheid bescheid) {
+		var result = new HashMap<String, Object>();
+		result.put(Bescheid.FIELD_BEWILLIGT, bescheid.isBewilligt());
+		mapBeschiedenAm(bescheid).ifPresent(beschiedenAm -> result.put(Bescheid.FIELD_BESCHIEDEN_AM, beschiedenAm));
+		mapStatus(bescheid).ifPresent(status -> result.put(Bescheid.FIELD_STATUS, status));
+		mapBescheidDocument(bescheid).ifPresent(bescheidDocumentId -> result.put(Bescheid.FIELD_BESCHEID_DOCUMENT, bescheidDocumentId));
+		mapSendBy(bescheid).ifPresent(sendBy -> result.put(Bescheid.FIELD_SEND_BY, sendBy));
+		bescheid.getNachrichtSubject().ifPresent(subject -> result.put(Bescheid.FIELD_NACHRICHT_SUBJECT, subject));
+		bescheid.getNachrichtText().ifPresent(text -> result.put(Bescheid.FIELD_NACHRICHT_TEXT, text));
+		mapSentInfo(bescheid).ifPresent(sentInfo -> result.put(FIELD_SENT_INFO, sentInfo));
+		mapAttachmentIds(bescheid.getAttachments()).ifPresent(attachmentIds -> result.put(FIELD_ATTACHMENTS, attachmentIds));
+		return Collections.unmodifiableMap(result);
 	}
 
-	@Mapping(target = "mergeFrom", ignore = true)
-	@Mapping(target = "clearField", ignore = true)
-	@Mapping(target = "clearOneof", ignore = true)
-	@Mapping(target = "mergeFeatures", ignore = true)
-	@Mapping(target = "mergeUnknownFields", ignore = true)
-	@Mapping(target = "javaVersionBytes", ignore = true)
-	@Mapping(target = "unknownFields", ignore = true)
-	@Mapping(target = "versionBytes", ignore = true)
-	@Mapping(target = "allFields", ignore = true)
-	GrpcBescheidManagerConfigResponse fromBescheidManagerConfig(BescheidManagerConfig bescheidManagerConfig);
+	private Optional<String> mapBeschiedenAm(Bescheid bescheid) {
+		return Optional.ofNullable(bescheid.getBeschiedenAm()).map(LocalDate::toString);
+	}
 
-	@Mapping(target = "mergeFrom", ignore = true)
-	@Mapping(target = "clearField", ignore = true)
-	@Mapping(target = "clearOneof", ignore = true)
-	@Mapping(target = "mergeBescheid", ignore = true)
-	@Mapping(target = "mergeUnknownFields", ignore = true)
-	@Mapping(target = "unknownFields", ignore = true)
-	@Mapping(target = "allFields", ignore = true)
-	GrpcGetBescheidResponse toGetBescheidResponse(Bescheid bescheid);
+	private Optional<String> mapStatus(Bescheid bescheid) {
+		return Optional.ofNullable(bescheid.getStatus()).map(Bescheid.Status::name);
+	}
+
+	private Optional<String> mapBescheidDocument(Bescheid bescheid) {
+		return Optional.ofNullable(bescheid.getBescheidDocument()).map(FileId::toString);
+	}
+
+	private Optional<String> mapSendBy(Bescheid bescheid) {
+		return Optional.ofNullable(bescheid.getSendBy()).map(Bescheid.SendBy::name);
+	}
+
+	public Optional<Map<String, Object>> mapSentInfo(Bescheid bescheid) {
+		return Optional.ofNullable(bescheid.getSentInfo()).map(sentInfoMapper::toMap);
+	}
+
+	Optional<List<String>> mapAttachmentIds(List<FileId> attachments) {
+		return attachments.isEmpty() ? Optional.empty() : Optional.of(attachments.stream().map(FileId::toString).toList());
+	}
 
-	@Mapping(target = "mergeFrom", ignore = true)
-	@Mapping(target = "clearField", ignore = true)
-	@Mapping(target = "clearOneof", ignore = true)
-	@Mapping(target = "mergeBescheid", ignore = true)
-	@Mapping(target = "mergeUnknownFields", ignore = true)
-	@Mapping(target = "unknownFields", ignore = true)
-	@Mapping(target = "allFields", ignore = true)
-	GrpcGetBescheidDraftResponse toGetBescheidDraftResponse(Bescheid bescheid);
 }
\ No newline at end of file
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java
index 372e07eb95400196f7cb1d540716314f5994ef44..cd1d2fc2ccb45a29beedfc74b4d90b7ecc8d559f 100644
--- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java
@@ -1,13 +1,17 @@
 package de.ozgcloud.bescheid;
 
+import static java.util.Objects.*;
+
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import jakarta.annotation.PostConstruct;
@@ -22,7 +26,9 @@ import de.ozgcloud.apilib.common.command.OzgCloudCommand;
 import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
 import de.ozgcloud.apilib.common.command.OzgCloudCreateSubCommandsRequest;
 import de.ozgcloud.apilib.common.command.grpc.CommandMapper;
+import de.ozgcloud.bescheid.administration.AdministrationService;
 import de.ozgcloud.bescheid.attributes.ClientAttributeService;
+import de.ozgcloud.bescheid.common.freemarker.TemplateHandler;
 import de.ozgcloud.bescheid.common.user.UserProfileService;
 import de.ozgcloud.bescheid.vorgang.Vorgang;
 import de.ozgcloud.bescheid.vorgang.VorgangId;
@@ -39,7 +45,11 @@ import lombok.extern.log4j.Log4j2;
 @Service
 @Log4j2
 @RequiredArgsConstructor
-class BescheidService {
+public class BescheidService {
+
+	static final String DEFAULT_NACHRICHT_SUBJECT = "Ihr Bescheid zum Antrag";
+	public static final String DEFAULT_NACHRICHT_TEMPLATE_FILE = "bescheid.nachrichtTemplate.txt.ftlh";
+	public static final String KEY_TEMPLATE_SIGNATURE = "signature";
 
 	private static final String ERROR_MESSAGE_NO_SERVICE = "No Bescheid Endpoint is configured.";
 
@@ -60,12 +70,16 @@ class BescheidService {
 	private final UserProfileService userProfileService;
 	@Qualifier(BescheidManagerConfiguration.COMMAND_SERVICE_NAME)
 	private final OzgCloudCommandService commandService;
+	private final AdministrationService administrationService;
+
 	private final CommandMapper commandMapper;
 	private final ClientAttributeService bescheidClientAttributeService;
 	private final BuildProperties buildProperties;
 	private final Optional<BescheidRemoteService> remoteService;
 	private final BescheidMapper mapper;
 
+	private final TemplateHandler templateHandler;
+
 	@PostConstruct
 	void logStatus() {
 		remoteService.ifPresentOrElse(
@@ -74,13 +88,65 @@ class BescheidService {
 	}
 
 	public Optional<Bescheid> findDraft(String vorgangId) {
-		return attachedItemService.findBescheidItem(vorgangId).map(mapper::mapFromAttachedItem);
+		return attachedItemService.findBescheidItem(VorgangId.from(vorgangId)).map(mapper::mapFromAttachedItem);
 	}
 
 	public Stream<Bescheid> findAll(VorgangId vorgangId) {
 		return attachedItemService.findAllBescheid(vorgangId).stream().map(mapper::mapFromAttachedItem);
 	}
 
+	public String createBescheidDraft(Command createBescheidDraftCommand) {
+		validateBescheidData(createBescheidDraftCommand.getBodyObject());
+		return attachedItemService.createBescheidDraft(buildBescheidDraft(createBescheidDraftCommand));
+	}
+
+	void validateBescheidData(Map<String, Object> bodyObject) {
+		validateBescheidField(bodyObject, Bescheid.FIELD_BESCHIEDEN_AM);
+		validateBescheidField(bodyObject, Bescheid.FIELD_BEWILLIGT);
+		validateSendBy(MapUtils.getString(bodyObject, Bescheid.FIELD_SEND_BY));
+	}
+
+	void validateBescheidField(Map<String, Object> bescheid, String field) {
+		if (isNull(bescheid.get(field))) {
+			throw new TechnicalException("Fields '%s' is required for bescheid creation".formatted(field));
+		}
+	}
+
+	void validateSendBy(String sendBy) {
+		if (isUnknownSendByValue(sendBy)) {
+			var possibleSendByValues = Arrays.stream(Bescheid.SendBy.values()).map(Bescheid.SendBy::name)
+					.collect(Collectors.joining(","));
+			var message = String.format("Unexpected value for field '%s': %s. Allowed are: %s", Bescheid.FIELD_SEND_BY, sendBy,
+					possibleSendByValues);
+			throw new TechnicalException(message);
+		}
+	}
+
+	private boolean isUnknownSendByValue(String sendByValue) {
+		return Arrays.stream(Bescheid.SendBy.values()).noneMatch(sendBy -> sendBy.hasValue(sendByValue));
+	}
+
+	Bescheid buildBescheidDraft(Command command) {
+		var bescheid = mapper.mapFromCommand(command);
+		var resultBuilder = bescheid.toBuilder().id(null).version(0).status(Bescheid.Status.DRAFT);
+		if (bescheid.getNachrichtSubject().isEmpty()) {
+			resultBuilder.nachrichtSubject(Optional.of(DEFAULT_NACHRICHT_SUBJECT));
+		}
+		if (bescheid.getNachrichtText().isEmpty()) {
+			resultBuilder.nachrichtText(Optional.of(createNachrichtText()));
+		}
+		return resultBuilder.build();
+	}
+
+	String createNachrichtText() {
+		return templateHandler.fillTemplate(DEFAULT_NACHRICHT_TEMPLATE_FILE, getTemplateParameters());
+	}
+
+	Map<String, Object> getTemplateParameters() {
+		return administrationService.getNachrichtSignature().map(signature -> Map.<String, Object>of(KEY_TEMPLATE_SIGNATURE, signature))
+				.orElseGet(Collections::emptyMap);
+	}
+
 	public BescheidResponse createBescheid(BescheidRequest request) {
 		checkRemoteService();
 
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/SentInfoMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/SentInfoMapper.java
index a16e4a4aa3a7717c0c74905602962de176537df4..95c5b586e88adc7881815f3331ad7213f5bcb530 100644
--- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/SentInfoMapper.java
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/SentInfoMapper.java
@@ -1,5 +1,12 @@
 package de.ozgcloud.bescheid;
 
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.collections.MapUtils;
 import org.mapstruct.CollectionMappingStrategy;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
@@ -8,6 +15,9 @@ import org.mapstruct.ReportingPolicy;
 @Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
 public interface SentInfoMapper {
 
+	String GRPC_DATE_TIME_FORMATTER = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+
+	@Mapping(target = "defaultInstanceForType", ignore = true)
 	@Mapping(target = "mergeFrom", ignore = true)
 	@Mapping(target = "clearField", ignore = true)
 	@Mapping(target = "clearOneof", ignore = true)
@@ -16,6 +26,20 @@ public interface SentInfoMapper {
 	@Mapping(target = "sentByBytes", ignore = true)
 	@Mapping(target = "unknownFields", ignore = true)
 	@Mapping(target = "allFields", ignore = true)
-	@Mapping(target = "sentAt", source = "sentAt", dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'")
+	@Mapping(target = "sentAt", source = "sentAt", dateFormat = GRPC_DATE_TIME_FORMATTER)
 	GrpcSentInfo mapTo(SentInfo sentInfo);
+
+	default SentInfo toSentInfo(Map<String, Object> sentInfoMap) {
+		return SentInfo.builder()
+				.sentBy(MapUtils.getString(sentInfoMap, SentInfo.FIELD_SENT_BY))
+				.sentAt(ZonedDateTime.parse(MapUtils.getString(sentInfoMap, SentInfo.FIELD_SENT_AT), DateTimeFormatter.ISO_DATE_TIME))
+				.build();
+	}
+
+	default Map<String, Object> toMap(SentInfo sentInfo) {
+		var result = new HashMap<String, Object>();
+		result.put(SentInfo.FIELD_SENT_BY, sentInfo.getSentBy());
+		result.put(SentInfo.FIELD_SENT_AT, sentInfo.getSentAt().format(DateTimeFormatter.ISO_DATE_TIME));
+		return Collections.unmodifiableMap(result);
+	}
 }
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationProperties.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..59f93a0239f649eb4156fb5512494e06749066d9
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationProperties.java
@@ -0,0 +1,44 @@
+/*
+ * 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
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.administration;
+
+import java.util.Optional;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@RefreshScope
+@Configuration
+@ConfigurationProperties(prefix = "ozgcloud.postfach")
+public class AdministrationProperties {
+
+	private Optional<String> signatur = Optional.empty();
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationService.java
new file mode 100644
index 0000000000000000000000000000000000000000..920c5ea67d8285d1646b7840bf6c5fd91fb8c1ab
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationService.java
@@ -0,0 +1,47 @@
+/*
+ * 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
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.administration;
+
+import java.util.Optional;
+
+import org.springframework.cloud.endpoint.RefreshEndpoint;
+import org.springframework.stereotype.Service;
+
+import lombok.RequiredArgsConstructor;
+
+@Service
+@RequiredArgsConstructor
+public class AdministrationService {
+
+	private final AdministrationProperties administrationProperties;
+	private final RefreshEndpoint refreshEndpoint;
+
+	public Optional<String> getNachrichtSignature() {
+		return administrationProperties.getSignatur();
+	}
+
+	public void refreshConfig() {
+		refreshEndpoint.refresh();
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationSyncScheduler.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationSyncScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..41fde870cc01fe94e9d2089742e77ffffd6a3f4a
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationSyncScheduler.java
@@ -0,0 +1,43 @@
+/*
+ * 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
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.administration;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import lombok.RequiredArgsConstructor;
+
+@Component
+@ConditionalOnProperty(value = "ozgcloud.administration.sync.enabled", havingValue = "true", matchIfMissing = true)
+@RequiredArgsConstructor
+public class AdministrationSyncScheduler {
+
+	private final AdministrationService service;
+
+	@Scheduled(initialDelayString = "${ozgcloud.administration.sync.delay}", fixedDelayString = "${ozgcloud.administration.sync.delay}")
+	public void sync() {
+		service.refreshConfig();
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemMapper.java
index 73d20952c8b05bf3fa0dd93c8d284c7583c319a5..c3431d175ebf43e14f6a7fd15baf34cb7b81a5f6 100644
--- a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemMapper.java
+++ b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemMapper.java
@@ -23,13 +23,25 @@
  */
 package de.ozgcloud.common.attached_item;
 
+import java.util.Map;
+
 import org.mapstruct.Mapper;
+import org.mapstruct.NullValueCheckStrategy;
 
 import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
 import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem;
 
-@Mapper(uses = { GrpcObjectMapper.class })
+@Mapper(uses = { GrpcObjectMapper.class }, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
 public interface AttachedItemMapper {
 
 	AttachedItem mapFromVorgangAttachedItem(GrpcVorgangAttachedItem item);
+
+	default Map<String, Object> toMap(AttachedItem attachedItem) {
+		return Map.of(
+				AttachedItem.PROPERTY_VORGANG_ID, attachedItem.getVorgangId(),
+				AttachedItem.PROPERTY_CLIENT, attachedItem.getClient(),
+				AttachedItem.PROPERTY_ITEM_NAME, attachedItem.getItemName(),
+				AttachedItem.PROPERTY_ITEM, attachedItem.getItem());
+	}
+
 }
\ No newline at end of file
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemService.java b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemService.java
index 551279332894c5c12395a7a43a2a93de52c180dc..d0ad2ed4e32a2eb9fe424440629f23e0e50e9331 100644
--- a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemService.java
+++ b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemService.java
@@ -23,15 +23,11 @@
  */
 package de.ozgcloud.common.attached_item;
 
-import static java.util.Objects.*;
-
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
-import java.util.stream.Collectors;
 
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -45,7 +41,7 @@ import de.ozgcloud.bescheid.Bescheid;
 import de.ozgcloud.bescheid.Bescheid.Status;
 import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor;
 import de.ozgcloud.bescheid.BescheidManagerConfiguration;
-import de.ozgcloud.bescheid.common.freemarker.TemplateHandler;
+import de.ozgcloud.bescheid.BescheidMapper;
 import de.ozgcloud.bescheid.vorgang.VorgangId;
 import de.ozgcloud.command.Command;
 import de.ozgcloud.common.errorhandling.TechnicalException;
@@ -62,16 +58,15 @@ public class AttachedItemService {
 	static final String UPDATE_ATTACHED_ITEM_ORDER = "UPDATE_ATTACHED_ITEM";
 	static final String DELETE_ATTACHED_ITEM = "DELETE_ATTACHED_ITEM";
 
-	static final String DEFAULT_SUBJECT = "Ihr Bescheid zum Antrag";
-	static final String DEFAULT_TEMPLATE_FILE = "bescheid.nachrichtTemplate.txt.ftlh";
-
 	@Qualifier(BescheidManagerConfiguration.COMMAND_SERVICE_NAME)
 	private final OzgCloudCommandService commandService;
 	private final VorgangAttachedItemRemoteService remoteService;
+
 	private final CommandMapper commandMapper;
-	private final TemplateHandler templateHandler;
+	private final AttachedItemMapper attachedItemMapper;
+	private final BescheidMapper bescheidMapper;
 
-	public Optional<AttachedItem> findBescheidItem(String vorgangId) {
+	public Optional<AttachedItem> findBescheidItem(VorgangId vorgangId) {
 		return remoteService.findBescheidDraft(vorgangId);
 	}
 
@@ -79,41 +74,20 @@ public class AttachedItemService {
 		return remoteService.getItem(id);
 	}
 
-	public String createBescheidDraft(Command command) {
-		validateBescheidData(command.getBodyObject());
-		return remoteService.findBescheidDraft(command.getVorgangId())
-				.map(bescheid -> overrideAttachedItem(bescheid, command)).orElseGet(() -> createAttachedItem(command));
-	}
-
-	void validateBescheidData(Map<String, Object> bodyObject) {
-		validateBescheidField(bodyObject, Bescheid.FIELD_BESCHIEDEN_AM);
-		validateBescheidField(bodyObject, Bescheid.FIELD_BEWILLIGT);
-		validateSendBy(getSendBy(bodyObject));
-	}
-
-	void validateBescheidField(Map<String, Object> bescheid, String field) {
-		if (isNull(bescheid.get(field))) {
-			throw new TechnicalException("Fields '%s' is required for bescheid creation".formatted(field));
-		}
-	}
-
-	void validateSendBy(String sendBy) {
-		if (isUnknownSendByValue(sendBy)) {
-			var possibleSendByValues = Arrays.stream(Bescheid.SendBy.values()).map(Bescheid.SendBy::name)
-					.collect(Collectors.joining(","));
-			var message = String.format("Unexpected value for field '%s': %s. Allowed are: %s", Bescheid.FIELD_SEND_BY, sendBy,
-					possibleSendByValues);
-			throw new TechnicalException(message);
-		}
+	public String createBescheidDraft(Bescheid bescheidDraft) {
+		return remoteService.findBescheidDraft(bescheidDraft.getVorgangId())
+				.map(bescheidItem -> overrideAttachedItem(mergeBescheidDrafts(bescheidItem, bescheidDraft)))
+				.orElseGet(() -> createAttachedItem(bescheidDraft));
 	}
 
-	private boolean isUnknownSendByValue(String sendByValue) {
-		return Arrays.stream(Bescheid.SendBy.values()).noneMatch(sendBy -> sendBy.hasValue(sendByValue));
+	AttachedItem mergeBescheidDrafts(AttachedItem existingBescheidItem, Bescheid newBescheidDraft) {
+		return existingBescheidItem.toBuilder()
+				.item(bescheidMapper.mapToItem(newBescheidDraft))
+				.build();
 	}
 
-	String overrideAttachedItem(AttachedItem bescheidItem, Command command) {
-		var attachedItem = buildAttachedItemAsMap(command, buildItemMapWithAllBescheidFields(command));
-		var finishedOzgCloudCommand = commandService.createAndWaitUntilDone(buildPatchAttachedItemCommand(bescheidItem, attachedItem));
+	String overrideAttachedItem(AttachedItem bescheidItem) {
+		var finishedOzgCloudCommand = commandService.createAndWaitUntilDone(buildPatchAttachedItemCommand(bescheidItem, bescheidItem.getItem()));
 		return finishedOzgCloudCommand.getCreatedResource();
 	}
 
@@ -178,16 +152,17 @@ public class AttachedItemService {
 				.build();
 	}
 
-	String createAttachedItem(Command command) {
-		return commandService.createAndWaitUntilDone(buildCreateAttachedItemCommand(command)).getCreatedResource();
+	String createAttachedItem(Bescheid bescheidDraft) {
+		var bescheidItem = bescheidMapper.mapFromBescheid(bescheidDraft);
+		return commandService.createAndWaitUntilDone(buildCreateAttachedItemCommand(bescheidItem)).getCreatedResource();
 	}
 
-	OzgCloudCommand buildCreateAttachedItemCommand(Command command) {
+	OzgCloudCommand buildCreateAttachedItemCommand(AttachedItem bescheidItem) {
 		return OzgCloudCommand.builder()
-				.vorgangId(commandMapper.toOzgCloudVorgangId(command.getVorgangId()))
-				.relationId(commandMapper.mapRelationId(command.getRelationId()))
+				.vorgangId(commandMapper.toOzgCloudVorgangId(bescheidItem.getVorgangId()))
+				.relationId(commandMapper.mapRelationId(bescheidItem.getVorgangId()))
 				.order(CREATE_ATTACHED_ITEM_ORDER)
-				.bodyObject(buildAttachedItemAsMap(command, buildCreateBescheidItemMap(command))).build();
+				.bodyObject(attachedItemMapper.toMap(bescheidItem)).build();
 	}
 
 	Map<String, Object> buildAttachedItemAsMap(Command command, Map<String, Object> itemMap) {
@@ -199,17 +174,6 @@ public class AttachedItemService {
 		return result;
 	}
 
-	Map<String, Object> buildCreateBescheidItemMap(Command command) {
-		var result = buildItemMapWithExistingBescheidFields(command);
-		if (StringUtils.isEmpty(getNachrichtSubject(command))) {
-			result.put(Bescheid.FIELD_NACHRICHT_SUBJECT, DEFAULT_SUBJECT);
-		}
-		if (StringUtils.isEmpty(getNachrichtText(command))) {
-			result.put(Bescheid.FIELD_NACHRICHT_TEXT, templateHandler.getRawTemplate(DEFAULT_TEMPLATE_FILE));
-		}
-		return result;
-	}
-
 	Map<String, Object> buildItemMapWithExistingBescheidFields(Command command) {
 		var result = buildItemMap(Bescheid.Status.DRAFT);
 		addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_BESCHIEDEN_AM, result);
@@ -222,14 +186,6 @@ public class AttachedItemService {
 		return result;
 	}
 
-	private String getNachrichtSubject(Command command) {
-		return MapUtils.getString(command.getBodyObject(), Bescheid.FIELD_NACHRICHT_SUBJECT);
-	}
-
-	private String getNachrichtText(Command command) {
-		return MapUtils.getString(command.getBodyObject(), Bescheid.FIELD_NACHRICHT_TEXT);
-	}
-
 	void addValueFromMapIfExists(Map<String, Object> sourceMap, String key, Map<String, Object> targetMap) {
 		if (sourceMap.containsKey(key)) {
 			targetMap.put(key, sourceMap.get(key));
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteService.java
index 6bc59454c9bd380608d7594e82a4df4f48174101..1d8756a0c968d0463e6f94391afb91fad9143c04 100644
--- a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteService.java
+++ b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteService.java
@@ -62,8 +62,8 @@ class VorgangAttachedItemRemoteService {
 	@Autowired
 	private AttachedItemMapper attachedItemMapper;
 
-	public Optional<AttachedItem> findBescheidDraft(String vorgangId) {
-		return findBescheidDraft(buildFindRequest(vorgangId));
+	public Optional<AttachedItem> findBescheidDraft(VorgangId vorgangId) {
+		return findBescheidDraft(buildFindRequest(vorgangId.toString()));
 	}
 
 	public List<AttachedItem> findAllBescheid(VorgangId vorgangId) {
diff --git a/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh b/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh
index 368804ed6ea51f622c32a2e90a21d5f1dd00763f..a16717f3fed5f7943af7f6cb701e085bdebeebb9 100644
--- a/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh
+++ b/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh
@@ -2,6 +2,6 @@ Sehr geehrte/r Antragsteller/in,
 
 im Folgenden erhalten Sie Ihren Bescheid.
 
-Mit freundlichen Grüßen
+${(signature)!"Mit freundlichen Grüßen
 
-Ihre Verwaltung
\ No newline at end of file
+Ihre Verwaltung"}
\ No newline at end of file
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java
index 2700586f2f8dd27bd9940ad790f6d2cc395370df..66403e2e7b83b2ac4ce30cb2b532cbdca881da64 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java
@@ -64,7 +64,7 @@ class BescheidEventListenerITCase {
 		void shouldCallService() {
 			publisher.publishEvent(CommandCreatedEventTestFactory.withCommand(command));
 
-			verify(attachedItemService).createBescheidDraft(command);
+			verify(service).createBescheidDraft(command);
 		}
 
 		@Test
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java
index 5d2d0689225962c1127644fe1f38063cb1e13c01..a3734e17d99a07d77410d213ebbe30415424cb1f 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java
@@ -106,14 +106,14 @@ class BescheidEventListenerTest {
 		void shouldCallCreateBescheidDraft() {
 			listener.doCreateBescheid(COMMAND);
 
-			verify(attachedItemService).createBescheidDraft(COMMAND);
+			verify(service).createBescheidDraft(COMMAND);
 		}
 
 		@Test
 		@DisplayName("should publish BescheidCreatedEvent after creating BescheidDraft")
 		void shouldPublishBescheidCreatedEventWithCommand() {
 			var createdResource = "item-id";
-			when(attachedItemService.createBescheidDraft(any())).thenReturn(createdResource);
+			when(service.createBescheidDraft(any())).thenReturn(createdResource);
 
 			listener.doCreateBescheid(COMMAND);
 
@@ -125,7 +125,7 @@ class BescheidEventListenerTest {
 		@DisplayName("should publish BescheidCreatedEvent with created resource")
 		void shouldPublishBescheidCreatedEventWithCreatedResource() {
 			var createdResource = "item-id";
-			when(attachedItemService.createBescheidDraft(any())).thenReturn(createdResource);
+			when(service.createBescheidDraft(any())).thenReturn(createdResource);
 
 			listener.doCreateBescheid(COMMAND);
 
@@ -497,7 +497,7 @@ class BescheidEventListenerTest {
 			private static final Command COMMAND = CommandTestFactory.createBuilder().relationId(AttachedItemTestFactory.ID)
 					.relationVersion(AttachedItemTestFactory.VERSION).bodyObject(AttachedItemTestFactory.createBescheidItem()).build();
 
-			private AttachedItem bescheidItem = createManuallyBescheidItem();
+			private final AttachedItem bescheidItem = createManuallyBescheidItem();
 
 			private AttachedItem createManuallyBescheidItem() {
 				var attachedItem = AttachedItemTestFactory.createBescheid();
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidMapperTest.java
index 8feda3dfe1ac673133247f758d71d3a413fa4a52..4e867c490dcc6bdcecd99e3b26cbc221caf686be 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidMapperTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidMapperTest.java
@@ -6,6 +6,7 @@ import static org.mockito.Mockito.*;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.lang3.StringUtils;
 import org.junit.jupiter.api.BeforeEach;
@@ -17,10 +18,14 @@ import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
 import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.CommandTestFactory;
+import de.ozgcloud.common.attached_item.AttachedItemService;
 import de.ozgcloud.common.attached_item.AttachedItemTestFactory;
+import de.ozgcloud.document.DocumentTestFactory;
 
 class BescheidMapperTest {
 
+	@Spy
 	@InjectMocks
 	private final BescheidMapper mapper = Mappers.getMapper(BescheidMapper.class);
 	@Spy
@@ -45,9 +50,7 @@ class BescheidMapperTest {
 		void shouldMapAllFields() {
 			var result = mapper.toBescheid(BescheidTestFactory.create());
 
-			assertThat(result).usingRecursiveComparison()
-					.ignoringFields("memoizedHashCode", "sentInfo_")
-					.isEqualTo(GrpcBescheidWithoutDocumentTestFactory.create());
+			assertThat(result).usingRecursiveComparison().isEqualTo(GrpcBescheidWithoutDocumentTestFactory.create());
 		}
 	}
 
@@ -120,4 +123,139 @@ class BescheidMapperTest {
 			assertThat(response).usingRecursiveComparison().isEqualTo(GrpcGetBescheidDraftResponseTestFactory.create());
 		}
 	}
+
+	@DisplayName("Map from command")
+	@Nested
+	class TestMapFromCommand {
+
+		@Test
+		void shouldMap() {
+			var command = CommandTestFactory.createBuilder().bodyObject(AttachedItemTestFactory.createBescheidItem())
+					.vorgangId(VorgangTestFactory.ID_STR).build();
+
+			var result = mapper.mapFromCommand(command);
+
+			assertThat(result).usingRecursiveComparison().ignoringFields("id", "version").isEqualTo(BescheidTestFactory.create());
+		}
+	}
+
+	@Nested
+	class TestMapFromBescheid {
+
+		@Test
+		void shouldSetClient() {
+			var result = mapper.mapFromBescheid(BescheidTestFactory.create());
+
+			assertThat(result.getClient()).isEqualTo(BescheidCallContextAttachingInterceptor.BESCHEID_MANAGER_CLIENT_NAME);
+		}
+
+		@Test
+		void shouldSetItemName() {
+			var result = mapper.mapFromBescheid(BescheidTestFactory.create());
+
+			assertThat(result.getItemName()).isEqualTo(AttachedItemService.BESCHEID_ITEM_NAME);
+		}
+
+		@Test
+		void shouldCallMapBescheidToItem() {
+			var bescheid = BescheidTestFactory.create();
+
+			mapper.mapFromBescheid(bescheid);
+
+			verify(mapper).mapToItem(bescheid);
+		}
+
+		@Test
+		void shouldSetItem() {
+			var itemMap = Map.<String, Object>of("key", "value");
+			doReturn(itemMap).when(mapper).mapToItem(any());
+
+			var result = mapper.mapFromBescheid(BescheidTestFactory.create());
+
+			assertThat(result.getItem()).isEqualTo(itemMap);
+		}
+	}
+
+	@Nested
+	class TestMapBescheidToItem {
+
+		@Test
+		void shouldSetBewilligt() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result).containsEntry(Bescheid.FIELD_BEWILLIGT, BescheidTestFactory.BEWILLIGT);
+		}
+
+		@Test
+		void shouldSetBeschiedenAm() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result).containsEntry(Bescheid.FIELD_BESCHIEDEN_AM, BescheidTestFactory.BESCHIEDEN_AM_STR);
+		}
+
+		@Test
+		void shouldSetStatus() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result).containsEntry(Bescheid.FIELD_STATUS, BescheidTestFactory.STATUS.name());
+		}
+
+		@Test
+		void shouldSetBescheidDocument() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result.get(Bescheid.FIELD_BESCHEID_DOCUMENT)).hasToString(DocumentTestFactory.ID);
+		}
+
+		@Test
+		void shouldSetSendBy() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result).containsEntry(Bescheid.FIELD_SEND_BY, BescheidTestFactory.SEND_BY.name());
+		}
+
+		@Test
+		void shouldSetNachrichtSubject() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result).containsEntry(Bescheid.FIELD_NACHRICHT_SUBJECT, BescheidTestFactory.NACHRICHT_SUBJECT);
+		}
+
+		@Test
+		void shouldSetNachrichtText() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result).containsEntry(Bescheid.FIELD_NACHRICHT_TEXT, BescheidTestFactory.NACHRICHT_TEXT);
+		}
+
+		@Test
+		void shouldCallSentInfoMapper() {
+			mapper.mapToItem(BescheidTestFactory.create());
+
+			verify(sentInfoMapper).toMap(BescheidTestFactory.SENT_INFO);
+		}
+
+		@Test
+		void shouldSetSentInfo() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result).containsEntry(Bescheid.FIELD_SENT_INFO, SentInfoTestFactory.asMap());
+		}
+
+		@Test
+		void shouldSetAttachments() {
+			var result = mapper.mapToItem(BescheidTestFactory.create());
+
+			assertThat(result).containsEntry(Bescheid.FIELD_ATTACHMENTS,
+					List.of(BescheidTestFactory.ATTACHMENT_STR, BescheidTestFactory.ATTACHMENT_STR));
+		}
+
+		@Test
+		void shouldNotAddEmptyEntries() {
+			var result = mapper.mapToItem(Bescheid.builder().build());
+
+			assertThat(result).containsOnlyKeys(Bescheid.FIELD_BEWILLIGT);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java
index 1bfa29f025365178aa5a66816db937b5670b2536..e593e429c550d90454013369ab01640091b5afef 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java
@@ -1,7 +1,6 @@
 package de.ozgcloud.bescheid;
 
 import static org.assertj.core.api.Assertions.*;
-import static org.assertj.core.api.InstanceOfAssertFactories.*;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -41,7 +40,9 @@ import de.ozgcloud.apilib.common.datatypes.GenericId;
 import de.ozgcloud.apilib.user.OzgCloudUserId;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
 import de.ozgcloud.bescheid.Bescheid.SendBy;
+import de.ozgcloud.bescheid.administration.AdministrationService;
 import de.ozgcloud.bescheid.attributes.ClientAttributeService;
+import de.ozgcloud.bescheid.common.freemarker.TemplateHandler;
 import de.ozgcloud.bescheid.common.user.UserProfile;
 import de.ozgcloud.bescheid.common.user.UserProfileService;
 import de.ozgcloud.bescheid.common.user.UserProfileTestFactory;
@@ -85,6 +86,10 @@ class BescheidServiceTest {
 	private BescheidRemoteService remoteService;
 	@Mock
 	private BescheidMapper mapper;
+	@Mock
+	private AdministrationService administrationService;
+	@Mock
+	private TemplateHandler templateHandler;
 
 	@BeforeEach
 	void init() {
@@ -108,7 +113,7 @@ class BescheidServiceTest {
 		void shouldCallVorgangAttachedItemRemoteService() {
 			service.findDraft(VorgangTestFactory.ID_STR);
 
-			verify(attachedItemService).findBescheidItem(VorgangTestFactory.ID_STR);
+			verify(attachedItemService).findBescheidItem(VorgangTestFactory.ID);
 		}
 
 		@Test
@@ -165,6 +170,254 @@ class BescheidServiceTest {
 		}
 	}
 
+	@Nested
+	class TestCreateBescheidDraft {
+
+		private static final Map<String, Object> COMMAND_BODY = Map.of("key", "value");
+		private static final Command COMMAND = CommandTestFactory.createBuilder().bodyObject(COMMAND_BODY).build();
+		private static final Bescheid BESCHEID_DRAFT = BescheidTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			doNothing().when(service).validateBescheidData(any());
+			doReturn(BESCHEID_DRAFT).when(service).buildBescheidDraft(any());
+		}
+
+		@Test
+		void shouldCallValidateBescheidData() {
+			service.createBescheidDraft(COMMAND);
+
+			verify(service).validateBescheidData(COMMAND_BODY);
+		}
+
+		@Test
+		void shouldCallAttachedItemService() {
+			service.createBescheidDraft(COMMAND);
+
+			verify(attachedItemService).createBescheidDraft(BESCHEID_DRAFT);
+		}
+
+		@Test
+		void shouldReturnResult() {
+			var createdBescheidId = "created-bescheid-id";
+			when(attachedItemService.createBescheidDraft(any(Bescheid.class))).thenReturn(createdBescheidId);
+
+			var result = service.createBescheidDraft(COMMAND);
+
+			assertThat(result).isEqualTo(createdBescheidId);
+		}
+	}
+
+	@Nested
+	class TestValidateBescheidData {
+
+		private static final Command CREATE_BESCHEID_DRAFT_COMMAND = CommandTestFactory.createBuilder()
+				.bodyObject(AttachedItemTestFactory.createBescheidItem()).build();
+
+		@Test
+		void shouldValidate() {
+			assertDoesNotThrow(() -> service.validateBescheidData(CREATE_BESCHEID_DRAFT_COMMAND.getBodyObject()));
+		}
+
+		@DisplayName("should fail if bescheidAm is missing")
+		@Test
+		void shouldThrowExceptionByBescheidAm() {
+			var map = Map.<String, Object>of(Bescheid.FIELD_BEWILLIGT, true);
+
+			assertThrows(TechnicalException.class, () -> service.validateBescheidData(map));
+		}
+
+		@DisplayName("should fail if bewilligt is missing")
+		@Test
+		void shouldThrowExceptionByBewilligt() {
+			var map = Map.<String, Object>of(Bescheid.FIELD_BESCHIEDEN_AM, "2021-01-01");
+
+			assertThrows(TechnicalException.class, () -> service.validateBescheidData(map));
+		}
+
+		@Test
+		void shouldValidateSendBy() {
+			var bodyObject = Map.<String, Object>of(Bescheid.FIELD_SEND_BY, SendBy.MANUAL.name());
+			doNothing().when(service).validateBescheidField(any(), any());
+
+			service.validateBescheidData(bodyObject);
+
+			verify(service).validateSendBy(SendBy.MANUAL.name());
+		}
+
+		@DisplayName("validate sendBy")
+		@Nested
+		class TestValidateSendBy {
+
+			@ValueSource(strings = { "not-exist", "" })
+			@ParameterizedTest
+			void shouldThrowExceptionOnNonExistingSendByValue(String sendBy) {
+				assertThrows(TechnicalException.class, () -> service.validateSendBy(sendBy));
+			}
+
+			@EnumSource(names = { "NACHRICHT", "MANUAL" })
+			@ParameterizedTest
+			void shouldNotThrowAnyExceptionOnExistingSendByValue(SendBy sendBy) {
+				assertDoesNotThrow(() -> service.validateSendBy(sendBy.name()));
+			}
+		}
+	}
+
+	@Nested
+	class TestBuildBescheidDraft {
+
+		private static final Command CREATE_BESCHEID_DRAFT_COMMAND = CommandTestFactory.createBuilder()
+				.bodyObject(AttachedItemTestFactory.createBescheidItem()).build();
+
+		private final Bescheid bescheid = BescheidTestFactory.createBuilder().status(Bescheid.Status.SENT).build();
+
+		@BeforeEach
+		void init() {
+			when(mapper.mapFromCommand(any())).thenReturn(bescheid);
+		}
+
+		@Test
+		void shouldCallMapFromCommand() {
+			buildBescheidDraft();
+
+			verify(mapper).mapFromCommand(CREATE_BESCHEID_DRAFT_COMMAND);
+		}
+
+		@Test
+		void shouldResetId() {
+			var result = buildBescheidDraft();
+
+			assertThat(result.getId()).isNull();
+		}
+
+		@Test
+		void shouldResetVersion() {
+			var result = buildBescheidDraft();
+
+			assertThat(result.getVersion()).isZero();
+		}
+
+		@Test
+		void shouldSetStatus() {
+			var result = buildBescheidDraft();
+
+			assertThat(result.getStatus()).isEqualTo(Bescheid.Status.DRAFT);
+		}
+
+		@Test
+		void shouldNotOverrideNachrichtSubject() {
+			var result = buildBescheidDraft();
+
+			assertThat(result.getNachrichtSubject()).contains(BescheidTestFactory.NACHRICHT_SUBJECT);
+		}
+
+		@Test
+		void shouldSetNachrichtSubject() {
+			var bescheid = BescheidTestFactory.createBuilder().nachrichtSubject(Optional.empty()).build();
+			when(mapper.mapFromCommand(any())).thenReturn(bescheid);
+
+			var result = buildBescheidDraft();
+
+			assertThat(result.getNachrichtSubject()).contains(BescheidService.SUBJECT);
+		}
+
+		@Test
+		void shouldNotOverrideNachrichtText() {
+			var result = buildBescheidDraft();
+
+			assertThat(result.getNachrichtText()).contains(BescheidTestFactory.NACHRICHT_TEXT);
+		}
+
+		@Test
+		void shouldCallCreateNachrichtText() {
+			var createdText = "created text";
+			doReturn(createdText).when(service).createNachrichtText();
+			var bescheid = BescheidTestFactory.createBuilder().nachrichtText(Optional.empty()).build();
+			when(mapper.mapFromCommand(any())).thenReturn(bescheid);
+
+			buildBescheidDraft();
+
+			verify(service).createNachrichtText();
+		}
+
+		@Test
+		void shouldSetNachrichtText() {
+			var createdText = "created text";
+			doReturn(createdText).when(service).createNachrichtText();
+			var bescheid = BescheidTestFactory.createBuilder().nachrichtText(Optional.empty()).build();
+			when(mapper.mapFromCommand(any())).thenReturn(bescheid);
+
+			var result = buildBescheidDraft();
+
+			assertThat(result.getNachrichtText()).contains(createdText);
+		}
+
+		private Bescheid buildBescheidDraft() {
+			return service.buildBescheidDraft(CREATE_BESCHEID_DRAFT_COMMAND);
+		}
+	}
+
+	@Nested
+	class TestCreateNachrichtText {
+
+		@Captor
+		private ArgumentCaptor<Map<String, Object>> signatureCaptor;
+
+		@Test
+		void shouldCallGetTemplateParameters() {
+			service.createNachrichtText();
+
+			verify(service).getTemplateParameters();
+		}
+
+		@Test
+		void shouldCallFillTemplate() {
+			var parameterMap = Map.<String, Object>of("key", "value");
+			doReturn(parameterMap).when(service).getTemplateParameters();
+
+			service.createNachrichtText();
+
+			verify(templateHandler).fillTemplate(BescheidService.DEFAULT_NACHRICHT_TEMPLATE_FILE, parameterMap);
+		}
+
+		@Test
+		void shouldReturnNachricht() {
+			when(templateHandler.fillTemplate(any(), any())).thenReturn(BescheidTestFactory.NACHRICHT_TEXT);
+
+			var result = service.createNachrichtText();
+
+			assertThat(result).isEqualTo(BescheidTestFactory.NACHRICHT_TEXT);
+		}
+	}
+
+	@Nested
+	class TestGetTemplateParameters {
+
+		@Test
+		void shouldCallAdministrationService() {
+			service.createNachrichtText();
+
+			verify(administrationService).getNachrichtSignature();
+		}
+
+		@Test
+		void shouldReturnParameters() {
+			var signature = "signature";
+			when(administrationService.getNachrichtSignature()).thenReturn(Optional.of(signature));
+
+			var result = service.getTemplateParameters();
+
+			assertThat(result).containsEntry(BescheidService.KEY_TEMPLATE_SIGNATURE, signature);
+		}
+
+		@Test
+		void shouldReturnEmptyMap() {
+			var result = service.getTemplateParameters();
+
+			assertThat(result).isEmpty();
+		}
+	}
+
 	@Nested
 	class TestCreateBescheid {
 
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java
index 9bbaa5728dc689fe6d70fe510af8ae909b65ae7f..b04cada3828d9fae6a85c5217c97df420972f353 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java
@@ -3,6 +3,7 @@ package de.ozgcloud.bescheid;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.info.BuildProperties;
 import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.cloud.endpoint.RefreshEndpoint;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
@@ -14,6 +15,8 @@ public class BescheidTestApplication {
 
 	@MockBean
 	private BuildProperties buildProperties;
+	@MockBean
+	private RefreshEndpoint refreshEndpoint;
 
 	@Bean
 	AuthenticationTrustResolver trustResolver() {
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java
index 326882334bbe54cd6987bf3eb812f1e086639642..7b90a2215cbddb56900ea293d7bbfd5cb9f44363 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java
@@ -19,6 +19,7 @@ public class BescheidTestFactory {
 
 	public final static boolean BEWILLIGT = true;
 
+	public final static BescheidId ID = BescheidId.from(AttachedItemTestFactory.ID);
 	public final static Status STATUS = Status.DRAFT;
 	public final static String BESCHIEDEN_AM_STR = "2021-01-10";
 	public final static LocalDate BESCHIEDEN_AM = LocalDate.parse(BESCHIEDEN_AM_STR);
@@ -39,7 +40,7 @@ public class BescheidTestFactory {
 
 	public static Bescheid.BescheidBuilder createBuilder() {
 		return Bescheid.builder()
-				.id(BescheidId.from(AttachedItemTestFactory.ID))
+				.id(ID)
 				.version(AttachedItemTestFactory.VERSION)
 				.vorgangId(VorgangTestFactory.ID)
 				.createdBy(UserProfileTestFactory.ID)
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/SentInfoMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/SentInfoMapperTest.java
index 2fa8f14b830b3c980e207d41ef1af3cafe69d00b..c3f9eea19a4f802f8214371b024f5bc3b7e08453 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/SentInfoMapperTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/SentInfoMapperTest.java
@@ -9,7 +9,7 @@ import org.mapstruct.factory.Mappers;
 
 class SentInfoMapperTest {
 
-	private SentInfoMapper mapper = Mappers.getMapper(SentInfoMapper.class);
+	private final SentInfoMapper mapper = Mappers.getMapper(SentInfoMapper.class);
 
 	@DisplayName("Map to")
 	@Nested
@@ -22,4 +22,28 @@ class SentInfoMapperTest {
 			assertThat(mappedSentInfo).usingRecursiveComparison().isEqualTo(GrpcSentInfoTestFactory.create());
 		}
 	}
+
+	@DisplayName("Map to SentInfo")
+	@Nested
+	class TestToSentInfo {
+
+		@Test
+		void shouldMap() {
+			var mappedSentInfo = mapper.toSentInfo(SentInfoTestFactory.asMap());
+
+			assertThat(mappedSentInfo).usingRecursiveComparison().isEqualTo(SentInfoTestFactory.create());
+		}
+	}
+
+	@DisplayName("As map")
+	@Nested
+	class TestAsMap {
+
+		@Test
+		void shouldMap() {
+			var mappedSentInfo = mapper.toMap(SentInfoTestFactory.create());
+
+			assertThat(mappedSentInfo).isEqualTo(SentInfoTestFactory.asMap());
+		}
+	}
 }
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/administration/AdministrationServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/administration/AdministrationServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..13e64879f85860b95b1e2a71154e56dced290343
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/administration/AdministrationServiceTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.administration;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.cloud.endpoint.RefreshEndpoint;
+
+class AdministrationServiceTest {
+
+	@InjectMocks
+	private AdministrationService service;
+
+	@Mock
+	private AdministrationProperties properties;
+	@Mock
+	private RefreshEndpoint refreshEndpoint;
+
+	@Nested
+	class GetNachrichtSignature {
+
+		@Test
+		void shouldCallGetSignature() {
+			service.getNachrichtSignature();
+
+			verify(properties).getSignatur();
+		}
+
+		@Test
+		void shouldReturnSignature() {
+			var signature = "signature";
+			when(properties.getSignatur()).thenReturn(Optional.of(signature));
+
+			var result = service.getNachrichtSignature();
+
+			assertThat(result).contains(signature);
+		}
+	}
+
+	@Nested
+	class TestRefreshConfig {
+
+		@Test
+		void shouldCallRefresh() {
+			service.refreshConfig();
+
+			verify(refreshEndpoint).refresh();
+		}
+	}
+}
\ No newline at end of file
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/freemarker/TemplateHandlerITCase.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/freemarker/TemplateHandlerITCase.java
index 071cb7d7ee00b57de1a217ccef7e4522df18a4c9..eeca8c0c770782be6364a6f9ae130e440a1168d7 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/freemarker/TemplateHandlerITCase.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/freemarker/TemplateHandlerITCase.java
@@ -2,6 +2,9 @@ package de.ozgcloud.bescheid.common.freemarker;
 
 import static org.assertj.core.api.Assertions.*;
 
+import java.util.Collections;
+import java.util.Map;
+
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -10,6 +13,7 @@ import org.springframework.boot.test.mock.mockito.MockBean;
 
 import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
 import de.ozgcloud.apilib.common.command.grpc.CommandMapper;
+import de.ozgcloud.bescheid.BescheidService;
 import de.ozgcloud.common.test.ITCase;
 
 @ITCase
@@ -39,4 +43,32 @@ class TemplateHandlerITCase {
 					.contains("Mit freundlichen Grüßen");
 		}
 	}
+
+	@DisplayName("Fill template")
+	@Nested
+	class TestFillTemplate {
+
+		@Test
+		void shouldReturnFilledTemplate() {
+			var signatur = "ganz andere Signatur";
+			var content = handler.fillTemplate(BescheidService.DEFAULT_NACHRICHT_TEMPLATE_FILE,
+					Map.of(BescheidService.KEY_TEMPLATE_SIGNATURE, signatur));
+
+			assertThat(content)
+					.contains("Sehr geehrte/r Antragsteller/in")
+					.contains("im Folgenden erhalten Sie Ihren Bescheid.")
+					.contains(signatur);
+		}
+
+		@Test
+		void shouldReturnWithDefaultValue() {
+			var content = handler.fillTemplate(BescheidService.DEFAULT_NACHRICHT_TEMPLATE_FILE, Collections.emptyMap());
+
+			assertThat(content)
+					.contains("Sehr geehrte/r Antragsteller/in")
+					.contains("im Folgenden erhalten Sie Ihren Bescheid.")
+					.contains("Mit freundlichen Grüßen")
+					.contains("Ihre Verwaltung");
+		}
+	}
 }
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemMapperTest.java
index 986f208f2f4ab75effbf1a4c42744624a2f8f202..25998524cc118900d7f705f2ff8c7268e2007b7b 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemMapperTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemMapperTest.java
@@ -27,6 +27,8 @@ import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Map;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -35,6 +37,8 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
+import de.ozgcloud.bescheid.SentInfoMapper;
+import de.ozgcloud.command.CommandTestFactory;
 import de.ozgcloud.document.DocumentService;
 import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
 
@@ -46,6 +50,8 @@ class AttachedItemMapperTest {
 
 	@Mock
 	private GrpcObjectMapper grpcObjectMapper;
+	@Mock
+	private SentInfoMapper sentInfoMapper;
 
 	@Nested
 	class TestMapFromVorgangAttachedItem {
@@ -64,4 +70,39 @@ class AttachedItemMapperTest {
 			assertThat(result).usingRecursiveComparison().isEqualTo(AttachedItemTestFactory.createDocument());
 		}
 	}
+
+	@Nested
+	class TestAsMap {
+
+		@Test
+		void shouldSetVorgangId() {
+			var result = mapper.toMap(AttachedItemTestFactory.createBescheid());
+
+			assertThat(result).containsEntry(AttachedItem.PROPERTY_VORGANG_ID, CommandTestFactory.VORGANG_ID);
+		}
+
+		@Test
+		void shouldSetClient() {
+			var result = mapper.toMap(AttachedItemTestFactory.createBescheid());
+
+			assertThat(result).containsEntry(AttachedItem.PROPERTY_CLIENT, AttachedItemTestFactory.CLIENT);
+		}
+
+		@Test
+		void shouldSetItemName() {
+			var result = mapper.toMap(AttachedItemTestFactory.createBescheid());
+
+			assertThat(result).containsEntry(AttachedItem.PROPERTY_ITEM_NAME, AttachedItemService.BESCHEID_ITEM_NAME);
+		}
+
+		@Test
+		void shouldSetItem() {
+			var item = Map.<String, Object>of("key", "value");
+			var attachedItem = AttachedItemTestFactory.createBescheidBuilder().clearItem().item(item).build();
+
+			var result = mapper.toMap(attachedItem);
+
+			assertThat(result).containsEntry(AttachedItem.PROPERTY_ITEM, item);
+		}
+	}
 }
\ No newline at end of file
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemServiceTest.java
index 1c2e8557104da84c83ebc6d37565bc357c5461e9..aaa9b15a805e2c989b97f0d77577c2499ec18a56 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemServiceTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemServiceTest.java
@@ -34,32 +34,23 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 
-import org.apache.commons.lang3.StringUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
-import org.junit.jupiter.params.provider.ValueSource;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import com.thedeanda.lorem.LoremIpsum;
-
 import de.ozgcloud.apilib.common.command.OzgCloudCommand;
 import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
 import de.ozgcloud.apilib.common.command.grpc.CommandMapper;
 import de.ozgcloud.apilib.common.datatypes.GenericId;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
 import de.ozgcloud.bescheid.Bescheid;
-import de.ozgcloud.bescheid.Bescheid.SendBy;
 import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor;
+import de.ozgcloud.bescheid.BescheidMapper;
 import de.ozgcloud.bescheid.BescheidTestFactory;
-import de.ozgcloud.bescheid.common.freemarker.TemplateHandler;
 import de.ozgcloud.bescheid.vorgang.VorgangId;
 import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
 import de.ozgcloud.command.Command;
@@ -84,25 +75,24 @@ class AttachedItemServiceTest {
 	@Mock
 	private CommandMapper commandMapper;
 	@Mock
-
-	private TemplateHandler templateHandler;
+	private BescheidMapper bescheidMapper;
 
 	@Nested
 	class TestFindBescheidItem {
 
 		@Test
 		void shouldCallGetBescheidDraft() {
-			service.findBescheidItem(CommandTestFactory.VORGANG_ID);
+			service.findBescheidItem(VorgangTestFactory.ID);
 
-			verify(remoteService).findBescheidDraft(CommandTestFactory.VORGANG_ID);
+			verify(remoteService).findBescheidDraft(VorgangTestFactory.ID);
 		}
 
 		@Test
 		void shouldReturnBescheidItem() {
 			var expected = AttachedItemTestFactory.createBescheid();
-			when(remoteService.findBescheidDraft(anyString())).thenReturn(Optional.of(expected));
+			when(remoteService.findBescheidDraft(any(VorgangId.class))).thenReturn(Optional.of(expected));
 
-			var actual = service.findBescheidItem(CommandTestFactory.VORGANG_ID);
+			var actual = service.findBescheidItem(VorgangTestFactory.ID);
 
 			assertThat(actual).contains(expected);
 		}
@@ -112,286 +102,170 @@ class AttachedItemServiceTest {
 	class TestCreateBescheidDraft {
 
 		private static final String CREATED_ATTACHED_ITEM_ID = "attached-item-id";
+		private static final Bescheid BESCHEID = BescheidTestFactory.create();
 
 		private final AttachedItem bescheidItem = AttachedItemTestFactory.createBescheid();
-		private Command command = CommandTestFactory.createBuilder().bodyObject(AttachedItemTestFactory.createBescheidItem()).build();
 
 		@Mock
-		private OzgCloudCommand ozgCloudCommand;
-		@Captor
-		private ArgumentCaptor<AttachedItem> bescheidItemCaptor;
+		private AttachedItem updatedBescheidItem;
 
 		@Test
-		void shouldCallValidateData() {
+		void shouldCallGetBescheidDraft() {
 			doReturn(CREATED_ATTACHED_ITEM_ID).when(service).createAttachedItem(any());
 
-			service.createBescheidDraft(command);
+			service.createBescheidDraft(BESCHEID);
 
-			verify(service).validateBescheidData(command.getBodyObject());
+			verify(remoteService).findBescheidDraft(VorgangTestFactory.ID);
 		}
 
 		@Test
-		void shouldCallGetBescheidDraft() {
-			doReturn(CREATED_ATTACHED_ITEM_ID).when(service).createAttachedItem(any());
+		void shouldCallMergeBescheidDrafts() {
+			doReturn(CREATED_ATTACHED_ITEM_ID).when(service).overrideAttachedItem(any());
+			when(remoteService.findBescheidDraft(any(VorgangId.class))).thenReturn(Optional.of(bescheidItem));
 
-			service.createBescheidDraft(command);
+			service.createBescheidDraft(BESCHEID);
 
-			verify(remoteService).findBescheidDraft(CommandTestFactory.VORGANG_ID);
+			verify(service).mergeBescheidDrafts(bescheidItem, BESCHEID);
 		}
 
 		@Test
-		void shouldCallUpdateBescheidDraft() {
-			doReturn(CREATED_ATTACHED_ITEM_ID).when(service).overrideAttachedItem(any(), any());
-			when(remoteService.findBescheidDraft(anyString())).thenReturn(Optional.of(bescheidItem));
+		void shouldCallOverrideAttachedItem() {
+			doReturn(CREATED_ATTACHED_ITEM_ID).when(service).overrideAttachedItem(any());
+			when(remoteService.findBescheidDraft(any(VorgangId.class))).thenReturn(Optional.of(bescheidItem));
+			doReturn(updatedBescheidItem).when(service).mergeBescheidDrafts(any(), any());
 
-			service.createBescheidDraft(command);
+			service.createBescheidDraft(BESCHEID);
 
-			verify(service).overrideAttachedItem(bescheidItemCaptor.capture(), eq(command));
-			assertThat(bescheidItemCaptor.getValue()).isEqualTo(bescheidItem);
+			verify(service).overrideAttachedItem(updatedBescheidItem);
 		}
 
 		@Test
 		void shouldCallCreateBescheidDraft() {
 			doReturn(CREATED_ATTACHED_ITEM_ID).when(service).createAttachedItem(any());
 
-			service.createBescheidDraft(command);
+			service.createBescheidDraft(BESCHEID);
 
-			verify(service).createBescheidDraft(command);
+			verify(service).createBescheidDraft(BESCHEID);
 		}
 
-		@Nested
-		class TestCreateAttachedItem {
-
-			@Mock
-			private OzgCloudCommand createAttachedItemCommand;
-
-			@BeforeEach
-			void init() {
-				when(commandService.createAndWaitUntilDone(any())).thenReturn(ozgCloudCommand);
-			}
-
-			@Test
-			void shouldCallBuildCreateAttachedItemCommand() {
-				createAttachedItem();
-
-				verify(service).buildCreateAttachedItemCommand(command);
-			}
+	}
 
-			@Test
-			void shouldCallCommandService() {
-				doReturn(createAttachedItemCommand).when(service).buildCreateAttachedItemCommand(any());
+	@Nested
+	class TestCreateAttachedItem {
 
-				createAttachedItem();
+		private static final Bescheid BESCHEID = BescheidTestFactory.create();
+		private static final AttachedItem BESCHEID_ITEM = AttachedItemTestFactory.createBescheid();
 
-				verify(commandService).createAndWaitUntilDone(createAttachedItemCommand);
-			}
+		@Mock
+		private OzgCloudCommand createAttachedItemCommand;
+		@Mock
+		private OzgCloudCommand finishedOzgCloudCommand;
 
-			private void createAttachedItem() {
-				service.createAttachedItem(command);
-			}
+		@BeforeEach
+		void init() {
+			when(commandService.createAndWaitUntilDone(any())).thenReturn(finishedOzgCloudCommand);
+			when(finishedOzgCloudCommand.getCreatedResource()).thenReturn(AttachedItemTestFactory.ID);
+			when(bescheidMapper.mapFromBescheid(any())).thenReturn(BESCHEID_ITEM);
 		}
 
-		@Nested
-		class TestBuildCreateAttachedItemCommand {
-
-			@Test
-			void shouldCallVorgangIdMapper() {
-				service.buildCreateAttachedItemCommand(command);
-
-				verify(commandMapper).toOzgCloudVorgangId(CommandTestFactory.VORGANG_ID);
-			}
-
-			@Test
-			void shouldSetVorgangId() {
-				var expectedVorgangId = OzgCloudVorgangId.from(CommandTestFactory.VORGANG_ID);
-				when(commandMapper.toOzgCloudVorgangId(any())).thenReturn(expectedVorgangId);
-
-				var result = service.buildCreateAttachedItemCommand(command);
-
-				assertThat(result.getVorgangId()).isEqualTo(expectedVorgangId);
-			}
-
-			@Test
-			void shouldCallRelationIdMapper() {
-				var expectedRelationId = "relationId";
-				command = CommandTestFactory.createBuilder().relationId(expectedRelationId).build();
-				when(commandMapper.mapRelationId(any())).thenReturn(GenericId.from(command.getRelationId()));
-
-				service.buildCreateAttachedItemCommand(command);
-
-				verify(commandMapper).mapRelationId(expectedRelationId);
-			}
-
-			@Test
-			void shouldSetRelationId() {
-				var expectedRelationId = "relationId";
-				command = CommandTestFactory.createBuilder().relationId(expectedRelationId).build();
-				when(commandMapper.mapRelationId(any())).thenReturn(GenericId.from(command.getRelationId()));
-
-				var result = service.buildCreateAttachedItemCommand(command);
-
-				assertThat(result.getRelationId()).hasToString(command.getRelationId());
-			}
-
-			@Test
-			void shouldCallBuildAttachedItemAsMap() {
-				var expectedItemMap = Map.<String, Object>of("key", "value");
-				doReturn(expectedItemMap).when(service).buildCreateBescheidItemMap(any());
-
-				service.buildCreateAttachedItemCommand(command);
-
-				verify(service).buildAttachedItemAsMap(command, expectedItemMap);
-			}
-
-			@Test
-			void shouldSetBodyObject() {
-				var expectedBodyObject = Map.<String, Object>of("key", "value");
-				doReturn(expectedBodyObject).when(service).buildAttachedItemAsMap(any(), any());
-
-				var result = service.buildCreateAttachedItemCommand(command);
-
-				assertThat(result.getBodyObject()).containsAllEntriesOf(expectedBodyObject);
-			}
-
-			@Test
-			void shouldSetOrder() {
-				var result = service.buildCreateAttachedItemCommand(command);
+		@Test
+		void shouldCallMapFromBescheid() {
+			createAttachedItem();
 
-				assertThat(result.getOrder()).isEqualTo(AttachedItemService.CREATE_ATTACHED_ITEM_ORDER);
-			}
+			verify(bescheidMapper).mapFromBescheid(BESCHEID);
 		}
 
-		@DisplayName("Build create bescheid itemMap")
-		@Nested
-		class TestBuildCreateBescheidItemMap {
-
-			private static final String TEMPLATE_CONTENT_AS_STRING = LoremIpsum.getInstance().getParagraphs(5, 20);
-
-			@DisplayName("on empty nachricht")
-			@Nested
-			class TestOnEmptyNachricht {
-
-				@Test
-				void shouldHaveDefaultNachrichtSubjectInBodyIfMissing() {
-					var bodyObject = service.buildCreateBescheidItemMap(createCommandWithoutNachricht());
-
-					assertThat(bodyObject).containsEntry(Bescheid.FIELD_NACHRICHT_SUBJECT, AttachedItemService.DEFAULT_SUBJECT);
-				}
-
-				@Test
-				void shouldCallTemplateHandler() {
-					when(templateHandler.getRawTemplate(any())).thenReturn(TEMPLATE_CONTENT_AS_STRING);
-
-					service.buildCreateBescheidItemMap(createCommandWithoutNachricht());
+		@Test
+		void shouldCallBuildCreateAttachedItemCommand() {
+			doReturn(createAttachedItemCommand).when(service).buildCreateAttachedItemCommand(any());
 
-					verify(templateHandler).getRawTemplate(AttachedItemService.DEFAULT_TEMPLATE_FILE);
-				}
+			createAttachedItem();
 
-				@Test
-				void shouldHaveDefaultNachrichtTextInBodyIfMissing() {
-					when(templateHandler.getRawTemplate(any())).thenReturn(TEMPLATE_CONTENT_AS_STRING);
+			verify(service).buildCreateAttachedItemCommand(BESCHEID_ITEM);
+		}
 
-					var bodyObject = service.buildCreateBescheidItemMap(createCommandWithoutNachricht());
+		@Test
+		void shouldCallCommandService() {
+			doReturn(createAttachedItemCommand).when(service).buildCreateAttachedItemCommand(any());
 
-					assertThat(bodyObject).containsEntry(Bescheid.FIELD_NACHRICHT_TEXT, TEMPLATE_CONTENT_AS_STRING);
-				}
+			createAttachedItem();
 
-				private Command createCommandWithoutNachricht() {
-					var bescheidItemMap = AttachedItemTestFactory.createBescheidItem();
-					bescheidItemMap.put(Bescheid.FIELD_NACHRICHT_SUBJECT, StringUtils.EMPTY);
-					bescheidItemMap.put(Bescheid.FIELD_NACHRICHT_TEXT, StringUtils.EMPTY);
-					return CommandTestFactory.createBuilder().bodyObject(bescheidItemMap).build();
-				}
-			}
+			verify(commandService).createAndWaitUntilDone(createAttachedItemCommand);
+		}
 
-			@DisplayName("on non existing nachricht")
-			@Nested
-			class TestNonExistingNachricht {
+		@Test
+		void shouldReturnCreatedResource() {
+			var result = createAttachedItem();
 
-				@Test
-				void shouldHaveDefaultNachrichtSubjectInBodyIfMissing() {
-					var bodyObject = service.buildCreateBescheidItemMap(createCommandWithoutNachricht());
+			assertThat(result).isEqualTo(AttachedItemTestFactory.ID);
+		}
 
-					assertThat(bodyObject).containsEntry(Bescheid.FIELD_NACHRICHT_SUBJECT, AttachedItemService.DEFAULT_SUBJECT);
-				}
+		private String createAttachedItem() {
+			return service.createAttachedItem(BESCHEID);
+		}
+	}
 
-				@Test
-				void shouldCallTemplateHandler() {
-					when(templateHandler.getRawTemplate(any())).thenReturn(TEMPLATE_CONTENT_AS_STRING);
+	@Nested
+	class TestBuildCreateAttachedItemCommand {
 
-					service.buildCreateBescheidItemMap(createCommandWithoutNachricht());
+		private static final AttachedItem BESCHEID_ITEM = AttachedItemTestFactory.createBescheid();
 
-					verify(templateHandler).getRawTemplate(AttachedItemService.DEFAULT_TEMPLATE_FILE);
-				}
+		@Test
+		void shouldCallVorgangIdMapper() {
+			service.buildCreateAttachedItemCommand(BESCHEID_ITEM);
 
-				@Test
-				void shouldHaveDefaultNachrichtTextInBodyIfMissing() {
-					when(templateHandler.getRawTemplate(any())).thenReturn(TEMPLATE_CONTENT_AS_STRING);
+			verify(commandMapper).toOzgCloudVorgangId(CommandTestFactory.VORGANG_ID);
+		}
 
-					var bodyObject = service.buildCreateBescheidItemMap(createCommandWithoutNachricht());
+		@Test
+		void shouldSetVorgangId() {
+			var expectedVorgangId = OzgCloudVorgangId.from(CommandTestFactory.VORGANG_ID);
+			when(commandMapper.toOzgCloudVorgangId(any())).thenReturn(expectedVorgangId);
 
-					assertThat(bodyObject).containsEntry(Bescheid.FIELD_NACHRICHT_TEXT, TEMPLATE_CONTENT_AS_STRING);
-				}
+			var result = service.buildCreateAttachedItemCommand(BESCHEID_ITEM);
 
-				private Command createCommandWithoutNachricht() {
-					var bescheidItemMap = AttachedItemTestFactory.createBescheidItem();
-					bescheidItemMap.remove(Bescheid.FIELD_NACHRICHT_SUBJECT);
-					bescheidItemMap.remove(Bescheid.FIELD_NACHRICHT_TEXT);
-					return CommandTestFactory.createBuilder().bodyObject(bescheidItemMap).build();
-				}
-			}
+			assertThat(result.getVorgangId()).isEqualTo(expectedVorgangId);
 		}
 
-		@Nested
-		class TestValidateBescheidData {
+		@Test
+		void shouldCallRelationIdMapper() {
+			service.buildCreateAttachedItemCommand(BESCHEID_ITEM);
 
-			@Test
-			void shouldValidate() {
-				assertDoesNotThrow(() -> service.validateBescheidData(command.getBodyObject()));
-			}
+			verify(commandMapper).mapRelationId(CommandTestFactory.VORGANG_ID);
+		}
 
-			@DisplayName(value = "should fail if bescheidAm is missing")
-			@Test
-			void shouldThrowExceptionByBescheidAm() {
-				var map = Map.<String, Object>of(Bescheid.FIELD_BEWILLIGT, true);
+		@Test
+		void shouldSetRelationId() {
+			var expectedRelationId = "relationId";
+			when(commandMapper.mapRelationId(any())).thenReturn(GenericId.from(expectedRelationId));
 
-				assertThrows(TechnicalException.class, () -> service.validateBescheidData(map));
-			}
+			var result = service.buildCreateAttachedItemCommand(BESCHEID_ITEM);
 
-			@DisplayName(value = "should fail if bewilligt is missing")
-			@Test
-			void shouldThrowExceptionByBewilligt() {
-				var map = Map.<String, Object>of(Bescheid.FIELD_BESCHIEDEN_AM, "2021-01-01");
+			assertThat(result.getRelationId()).hasToString(expectedRelationId);
+		}
 
-				assertThrows(TechnicalException.class, () -> service.validateBescheidData(map));
-			}
+		@Test
+		void shouldSetOrder() {
+			var result = service.buildCreateAttachedItemCommand(BESCHEID_ITEM);
 
-			@Test
-			void shouldValidateSendBy() {
-				var bodyObject = Map.<String, Object>of(Bescheid.FIELD_SEND_BY, SendBy.MANUAL.name());
-				doNothing().when(service).validateBescheidField(any(), any());
+			assertThat(result.getOrder()).isEqualTo(AttachedItemService.CREATE_ATTACHED_ITEM_ORDER);
+		}
 
-				service.validateBescheidData(bodyObject);
+		@Test
+		void shouldCallAttachedItemMapper() {
+			service.buildCreateAttachedItemCommand(BESCHEID_ITEM);
 
-				verify(service).validateSendBy(SendBy.MANUAL.name());
-			}
+			verify(mapper).toMap(BESCHEID_ITEM);
+		}
 
-			@DisplayName("validate sendBy")
-			@Nested
-			class TestValidateSendBy {
+		@Test
+		void shouldSetBodyObject() {
+			var itemMap = Map.<String, Object>of("key", "value");
+			when(mapper.toMap(any())).thenReturn(itemMap);
 
-				@ValueSource(strings = { "not-exist", "" })
-				@ParameterizedTest
-				void shouldThrowExceptionOnNonExistingSendByValue(String sendBy) {
-					assertThrows(TechnicalException.class, () -> service.validateSendBy(sendBy));
-				}
+			var result = service.buildCreateAttachedItemCommand(BESCHEID_ITEM);
 
-				@EnumSource(names = { "NACHRICHT", "MANUAL" })
-				@ParameterizedTest
-				void shouldNotThrowAnyExceptionOnExistingSendByValue(SendBy sendBy) {
-					assertDoesNotThrow(() -> service.validateSendBy(sendBy.name()));
-				}
-			}
+			assertThat(result.getBodyObject()).containsAllEntriesOf(itemMap);
 		}
 	}
 
@@ -633,41 +507,22 @@ class AttachedItemServiceTest {
 	class TestOverrideAttachedItem {
 
 		private static final String CREATED_RESOURCE = "created-resource";
+
 		@Mock
 		private OzgCloudCommand updateItemCommand;
 
-		private final Command command = CommandTestFactory.createBuilder().bodyObject(AttachedItemTestFactory.createBescheidItem()).build();
-
 		@BeforeEach
 		void init() {
 			when(commandService.createAndWaitUntilDone(any())).thenReturn(updateItemCommand);
 			when(updateItemCommand.getCreatedResource()).thenReturn(CREATED_RESOURCE);
 		}
 
-		@Test
-		void shouldCallBuildItemMapWithAllBescheidFields() {
-			service.overrideAttachedItem(AttachedItemTestFactory.createBescheid(), command);
-
-			verify(service).buildItemMapWithAllBescheidFields(command);
-		}
-
-		@Test
-		void shouldCallBuildAttachedItemAsMap() {
-			var itemMap = Map.<String, Object>of("key", "value");
-			doReturn(itemMap).when(service).buildItemMapWithAllBescheidFields(any());
-
-			service.overrideAttachedItem(AttachedItemTestFactory.createBescheid(), command);
-
-			verify(service).buildAttachedItemAsMap(command, itemMap);
-		}
-
 		@Test
 		void shouldCallBuildUpdateAttachedItemCommand() {
 			var bodyObject = Map.<String, Object>of("key", "value");
-			doReturn(bodyObject).when(service).buildAttachedItemAsMap(any(), any());
-			var bescheidItem = AttachedItemTestFactory.createBescheid();
+			var bescheidItem = AttachedItemTestFactory.createBescheidBuilder().clearItem().item(bodyObject).build();
 
-			service.overrideAttachedItem(bescheidItem, command);
+			service.overrideAttachedItem(bescheidItem);
 
 			verify(service).buildPatchAttachedItemCommand(bescheidItem, bodyObject);
 		}
@@ -676,14 +531,14 @@ class AttachedItemServiceTest {
 		void shouldCallCommandService() {
 			doReturn(updateItemCommand).when(service).buildPatchAttachedItemCommand(any(), any());
 
-			service.overrideAttachedItem(AttachedItemTestFactory.createBescheid(), command);
+			service.overrideAttachedItem(AttachedItemTestFactory.createBescheid());
 
 			verify(commandService).createAndWaitUntilDone(updateItemCommand);
 		}
 
 		@Test
 		void shouldReturnCreatedResource() {
-			var result = service.overrideAttachedItem(AttachedItemTestFactory.createBescheid(), command);
+			var result = service.overrideAttachedItem(AttachedItemTestFactory.createBescheid());
 
 			assertThat(result).isEqualTo(CREATED_RESOURCE);
 		}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemTestFactory.java
index 6f95bc5930e980d4818394d9cf83cafcae4ab65f..9b3ac12ebfa3c1f1385bedaab9d8383c25c750a8 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemTestFactory.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemTestFactory.java
@@ -33,6 +33,7 @@ import java.util.Map;
 import de.ozgcloud.bescheid.Bescheid;
 import de.ozgcloud.bescheid.BescheidTestFactory;
 import de.ozgcloud.bescheid.SentInfo;
+import de.ozgcloud.bescheid.SentInfoTestFactory;
 import de.ozgcloud.bescheid.common.user.UserProfileTestFactory;
 import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
 import de.ozgcloud.command.CommandTestFactory;
@@ -47,6 +48,7 @@ public class AttachedItemTestFactory {
 	public static final String ID = "bescheid-item-id";
 	public static final long VERSION = 10L;
 	public static final String CLIENT = "client";
+	public static final Map<String, Object> SENT_INFO = SentInfoTestFactory.asMap();
 
 	public static AttachedItem create() {
 		return createBuilder().build();
@@ -64,7 +66,6 @@ public class AttachedItemTestFactory {
 
 	public static Map<String, Object> createBescheidItem() {
 		var item = new HashMap<String, Object>();
-		item.put(AttachedItem.PROPERTY_VORGANG_ID, VorgangTestFactory.ID);
 		item.put(Bescheid.FIELD_STATUS, BescheidTestFactory.STATUS.name());
 		item.put(Bescheid.FIELD_BESCHIEDEN_AM, BescheidTestFactory.BESCHIEDEN_AM_STR);
 		item.put(Bescheid.FIELD_BEWILLIGT, BescheidTestFactory.BEWILLIGT);
@@ -73,9 +74,8 @@ public class AttachedItemTestFactory {
 		item.put(Bescheid.FIELD_SEND_BY, BescheidTestFactory.SEND_BY.name());
 		item.put(Bescheid.FIELD_NACHRICHT_TEXT, BescheidTestFactory.NACHRICHT_TEXT);
 		item.put(Bescheid.FIELD_NACHRICHT_SUBJECT, BescheidTestFactory.NACHRICHT_SUBJECT);
-		item.put(Bescheid.FIELD_SENT_INFO, Map.of(
-				SentInfo.FIELD_SENT_BY, SENT_BY,
-				SentInfo.FIELD_SENT_AT, SENT_AT_STR));
+		item.put(Bescheid.FIELD_CREATED_BY, UserProfileTestFactory.ID_STR);
+		item.put(Bescheid.FIELD_SENT_INFO, SENT_INFO);
 		return item;
 	}
 
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteServiceTest.java
index 7e1a5140b048e87f07aa2c005f6595234a5ea669..104ace168b6b7486c39adf39df9657a825b8d577 100644
--- a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteServiceTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteServiceTest.java
@@ -58,8 +58,6 @@ import io.grpc.ClientInterceptor;
 
 class VorgangAttachedItemRemoteServiceTest {
 
-	private static final String VORGANG_ID = "vorgang-id";
-
 	@Spy
 	@InjectMocks
 	private VorgangAttachedItemRemoteService service;
@@ -78,8 +76,7 @@ class VorgangAttachedItemRemoteServiceTest {
 		private GrpcFindVorgangAttachedItemRequest request;
 
 		@Nested
-		@DisplayName("by vorgangId")
-		class TestGetByVorgangId {
+		class TestFindByVorgangId {
 
 			private static final AttachedItem BESCHEID_ITEM = AttachedItemTestFactory.createBescheid();
 
@@ -91,21 +88,21 @@ class VorgangAttachedItemRemoteServiceTest {
 
 			@Test
 			void shouldCallCreateFindRequestBuilder() {
-				service.findBescheidDraft(VORGANG_ID);
+				service.findBescheidDraft(VorgangTestFactory.ID);
 
-				verify(service).buildFindRequest(VORGANG_ID);
+				verify(service).buildFindRequest(VorgangTestFactory.ID_STR);
 			}
 
 			@Test
 			void shouldCallGetBescheidDraft() {
-				service.findBescheidDraft(VORGANG_ID);
+				service.findBescheidDraft(VorgangTestFactory.ID);
 
 				verify(service).findBescheidDraft(request);
 			}
 
 			@Test
 			void shouldReturnResult() {
-				var result = service.findBescheidDraft(VORGANG_ID);
+				var result = service.findBescheidDraft(VorgangTestFactory.ID);
 
 				assertThat(result).contains(BESCHEID_ITEM);
 			}
diff --git a/bescheid-manager/src/test/resources/application-itcase.yml b/bescheid-manager/src/test/resources/application-itcase.yml
index 8157581c058ea205d2708730f584327d24121e24..72e5c1342fce4a554381a3cc7d09cd4a09af48f7 100644
--- a/bescheid-manager/src/test/resources/application-itcase.yml
+++ b/bescheid-manager/src/test/resources/application-itcase.yml
@@ -6,6 +6,9 @@ logging:
   config: classpath:log4j2-local.xml
   
 ozgcloud:
+  admin:
+    sync:
+      enabled: false
   bescheid:
     smart-documents:
       url: https://demo-de.smartdocuments.com/wsxmldeposit/deposit/unattended
@@ -14,3 +17,7 @@ ozgcloud:
         password: MGM
       templateGroup: Kiel
       template: Halteverbot
+spring:
+  cloud:
+    config:
+      enabled: false
diff --git a/pom.xml b/pom.xml
index a4440748e7de59956874614bee775082340b163d..f27c49331eda7a4c8073d28ce417fb5b8ad22162 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.ozgcloud.vorgang</groupId>
 	<artifactId>vorgang-manager</artifactId>
-	<version>2.14.1</version>
+	<version>2.15.0-SNAPSHOT</version>
 
 	<name>OZG-Cloud Vorgang Manager</name>
 	<packaging>pom</packaging>
diff --git a/src/main/helm/templates/_helpers.tpl b/src/main/helm/templates/_helpers.tpl
index 9b9f1b39f8a671442b454742b293219a6bd0119d..d3319d470a404cdc82ea1f46d66de742c7b4662b 100644
--- a/src/main/helm/templates/_helpers.tpl
+++ b/src/main/helm/templates/_helpers.tpl
@@ -73,6 +73,10 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }}
 {{ printf "dns:///%s.%s:9090" .Values.vorgangmanagerName .Release.Namespace }}
 {{- end -}}
 
+{{- define "app.ozgcloud_administration_address" -}}
+{{ printf "http://%s.%s:8080" .Values.administrationName .Release.Namespace }}
+{{- end -}}
+
 {{- define "app.databaseSecretName" -}}
 {{- if (.Values.database).secretName -}}
 {{  .Values.database.secretName }}
diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
index 329fb56867a302145ce93e6d1d11e8384d795713..ba379a93e17e623cf46bbc3f6e05aa8750eacff8 100644
--- a/src/main/helm/templates/deployment.yaml
+++ b/src/main/helm/templates/deployment.yaml
@@ -63,6 +63,8 @@ spec:
             value: "/bindings"
           - name: spring_profiles_active
             value: {{ include "app.envSpringProfiles" . }}
+          - name: ozgcloud_application_address
+            value: {{ include "app.ozgcloud_vorgangmanager_address" . }}
           - name: ozgcloud_nachrichten-manager_address
             value: {{ include "app.ozgcloud_vorgangmanager_address" . }}
           {{- if .Values.env.ozgcloudAktenzeichen.enabled }}
@@ -154,7 +156,11 @@ spec:
           - name: ozgcloud_user-manager_url
             value: {{ include "app.ozgcloud_migration_user-manager_address" . }}
           - name: ozgcloud_zufi-manager_address
-            value: {{ .Values.zufiManager.address }}
+            value: {{ (.Values.zufiManager).address }}
+          - name: grpc_client_zufi-manager_address
+            value: {{ (.Values.zufiManager).address }}
+          - name: grpc_client_zufi-manager_negotiationType
+            value: {{ (.Values.zufiManager).grpcClientNegotiationType }}
           {{- if not (.Values.database).useExternal }}
           - name: spring_data_mongodb_uri
             valueFrom:
@@ -203,8 +209,9 @@ spec:
                 key: login
                 optional: false
           {{- end }}
-          
 
+          - name: ozgcloud_administration_address
+            value: {{ include "app.ozgcloud_administration_address" . }}
 
 
           {{- if ((.Values.ozgcloud).antragraum).enabled }}
@@ -229,6 +236,10 @@ spec:
           - name: ozgcloud_feature_bescheid_kielHackathonRoute
             value: {{ quote (((.Values.ozgcloud).feature).bescheid).kielHackathonRoute }}
           {{- end }}
+          {{- if (((.Values.ozgcloud).notification).eingangsbestaetigung).replyAllowed }}
+          - name: ozgcloud_notification_eingangsbestaetigung_replyAllowed
+            value: {{ quote (((.Values.ozgcloud).notification).eingangsbestaetigung).replyAllowed }}
+          {{- end }}
 
           {{- if (.Values.ozgcloud).processors}}
           {{- range $processor_index, $processor := (.Values.ozgcloud).processors }}
diff --git a/src/main/helm/values.yaml b/src/main/helm/values.yaml
index 7bad7a05a7dec07c8efafa98bf72f061afcde748..6a380e033dcf8986792b1e8b8ca9f92a4ab81a0c 100644
--- a/src/main/helm/values.yaml
+++ b/src/main/helm/values.yaml
@@ -57,8 +57,10 @@ vorgangmanagerName: vorgang-manager
 
 usermanagerName: user-manager
 
+administrationName: administration
+
 zufiManager:
-  address: dns:///zufi-manager.zufi:9090
+  address: dns:///zufi-server.zufi:9090
 
 elasticsearch:
     certificateSecretName: elasticsearch-certificate
diff --git a/src/test/helm/deployment_administration_address_env_test.yaml b/src/test/helm/deployment_administration_address_env_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b2bf2db3eed725512711a2f11cf87727c94e78bd
--- /dev/null
+++ b/src/test/helm/deployment_administration_address_env_test.yaml
@@ -0,0 +1,44 @@
+#
+# 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
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment administration address env
+release:
+  name: vorgang-manager
+  namespace: by-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+  imagePullSecret: image-pull-secret
+tests:
+  - it: should have set administration server address
+    set:
+      administrationName: custom_admin_name
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_administration_address
+            value: http://custom_admin_name.by-helm-test:8080
diff --git a/src/test/helm/deployment_env_test.yaml b/src/test/helm/deployment_env_test.yaml
index 573afcbdd936a8c2721f1706297fa5fca68f5d16..4d71e36a71fcb5da19e5c6b55afd44ad528bcbd8 100644
--- a/src/test/helm/deployment_env_test.yaml
+++ b/src/test/helm/deployment_env_test.yaml
@@ -140,4 +140,16 @@ tests:
           path: spec.template.spec.containers[0].env
           content:
             name: ozgcloud_processors_1_forms_0_formEngineName
-            value: FormSolutions
\ No newline at end of file
+            value: FormSolutions
+  - it: should have notification properties
+    set:
+      ozgcloud:
+        notification:
+          eingangsbestaetigung:
+            replyAllowed: true
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_notification_eingangsbestaetigung_replyAllowed
+            value: "true"
\ No newline at end of file
diff --git a/src/test/helm/deployment_vorgang_manager_env_test.yaml b/src/test/helm/deployment_vorgang_manager_env_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4626fa9296378d85086ac3e15513241aa785e23d
--- /dev/null
+++ b/src/test/helm/deployment_vorgang_manager_env_test.yaml
@@ -0,0 +1,42 @@
+#
+# 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
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment vorgang manager environment
+release:
+  name: vorgang-manager
+  namespace: by-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+  imagePullSecret: test-image-pull-secret
+tests:
+  - it: check if application address is set
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_application_address
+            value: dns:///vorgang-manager.by-helm-test:9090
\ No newline at end of file
diff --git a/src/test/helm/deployment_zufimanager_address_env_test.yaml b/src/test/helm/deployment_zufimanager_address_env_test.yaml
index 687a53ee8d0193969eeb7bb8471bd2f33deec6de..d73c2e5b39e192cfe0f30908ccaa4c2d5d22fe1c 100644
--- a/src/test/helm/deployment_zufimanager_address_env_test.yaml
+++ b/src/test/helm/deployment_zufimanager_address_env_test.yaml
@@ -22,10 +22,10 @@
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
 #
 
-suite: test environments
+suite: deployment zufi-manager address environment
 release:
   name: vorgang-manager
-  namespace: sh-helm-test
+  namespace: by-helm-test
 templates:
   - templates/deployment.yaml
 set:
@@ -33,10 +33,51 @@ set:
     environment: dev
   imagePullSecret: test-image-pull-secret
 tests:
-  - it: check if zufi-manager address is correct
+  - it: check default zufi-manager address
     asserts:
       - contains:
           path: spec.template.spec.containers[0].env
           content:
             name: ozgcloud_zufi-manager_address
-            value:  dns:///zufi-manager.zufi:9090
+            value: dns:///zufi-server.zufi:9090
+
+  - it: should set custom zufi-manager address
+    set:
+      zufiManager:
+        address: dns://other.zufi:9090
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_zufi-manager_address
+            value: dns://other.zufi:9090
+
+  - it: check default zufi-manager grpc client address
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_zufi-manager_address
+            value: dns:///zufi-server.zufi:9090
+
+  - it: should set custom zufi-manager grpc client address
+    set:
+      zufiManager:
+        address: dns://other.zufi:9090
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_zufi-manager_address
+            value: dns://other.zufi:9090
+
+  - it: check if zufi-manager negotiationType is set
+    set:
+      zufiManager:
+        grpcClientNegotiationType: NOT_DEFAULT
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_zufi-manager_negotiationType
+            value: NOT_DEFAULT
diff --git a/vorgang-manager-base/pom.xml b/vorgang-manager-base/pom.xml
index c46f9728c9675fed6cfbd1262232612d9db7092d..3330f384b382b6d0c1d4570dc8503d1ba745363c 100644
--- a/vorgang-manager-base/pom.xml
+++ b/vorgang-manager-base/pom.xml
@@ -12,7 +12,7 @@
 
 	<groupId>de.ozgcloud.vorgang</groupId>
 	<artifactId>vorgang-manager-base</artifactId>
-	<version>2.14.1</version>
+	<version>2.15.0-SNAPSHOT</version>
 
 	<name>OZG-Cloud Vorgang Manager Base</name>
 
diff --git a/vorgang-manager-command/pom.xml b/vorgang-manager-command/pom.xml
index 74645f55411e2dc996098d5151a226f3b9d4a2ee..90c93b9f28cbac4fc1a4b84c72ee49b9e56c99b1 100644
--- a/vorgang-manager-command/pom.xml
+++ b/vorgang-manager-command/pom.xml
@@ -10,7 +10,7 @@
 	
 	<groupId>de.ozgcloud.command</groupId>
 	<artifactId>command-manager</artifactId>
-	<version>2.14.1</version>
+	<version>2.15.0-SNAPSHOT</version>
 	<name>OZG-Cloud Command Manager</name>
 
 	<properties>
diff --git a/vorgang-manager-command/src/main/java/de/ozgcloud/command/PostfachNachrichtReceivedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/PostfachNachrichtReceivedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ed40fd7a5f9a371792f4971920a78e183211f53
--- /dev/null
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/PostfachNachrichtReceivedEvent.java
@@ -0,0 +1,50 @@
+/*
+ * 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
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.command;
+
+import java.io.Serial;
+
+import org.springframework.context.ApplicationEvent;
+
+import lombok.Getter;
+
+@Getter
+public class PostfachNachrichtReceivedEvent extends ApplicationEvent {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	private final String nachrichtId;
+
+	public PostfachNachrichtReceivedEvent(Command command, String nachrichtId) {
+		super(command);
+		this.nachrichtId = nachrichtId;
+	}
+
+	@Override
+	public Command getSource() {
+		return (Command) super.getSource();
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAssignedEvent.java
similarity index 74%
rename from vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAssignedEvent.java
index 7847c2522279ff910b9d0f0aec2c3e3d79eaa1b6..7515a5e69b0002b4c8ef91bcd0eb7c653ca6499d 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAssignedEvent.java
@@ -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
@@ -21,20 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.ozgcloud.vorgang.vorgang;
+package de.ozgcloud.command;
 
-import de.ozgcloud.command.Command;
-import de.ozgcloud.command.CommandExecutedEvent;
-import lombok.Getter;
-
-@Getter
 public class VorgangAssignedEvent extends CommandExecutedEvent {
-	private transient Command command;
 
 	private static final long serialVersionUID = 1L;
 
-	protected VorgangAssignedEvent(Command command) {
-		super(command.getId());
-		this.command = command;
+	public VorgangAssignedEvent(Command command) {
+		super(command);
 	}
 }
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAttachedItemCreatedEvent.java
similarity index 78%
rename from vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAttachedItemCreatedEvent.java
index baa5b5817df7e9130c043f8344d455e2f32fccb4..6ffbefae323b3cf0a6b9d3342a03a1ca6488eb00 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAttachedItemCreatedEvent.java
@@ -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
@@ -21,16 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.ozgcloud.vorgang.attached_item;
-
-import de.ozgcloud.command.CommandExecutedEvent;
+package de.ozgcloud.command;
 
 public class VorgangAttachedItemCreatedEvent extends CommandExecutedEvent {
 
 	private static final long serialVersionUID = 1L;
 
-	protected VorgangAttachedItemCreatedEvent(String commandId, String createdResource) {
-		super(commandId, createdResource);
+	public VorgangAttachedItemCreatedEvent(Command command, String createdResource) {
+		super(command, createdResource);
 	}
-
 }
diff --git a/vorgang-manager-interface/pom.xml b/vorgang-manager-interface/pom.xml
index 251378df84aec87d601c1162ba614828989e07df..2057978d5dba01316f9982e85efd173257f477b2 100644
--- a/vorgang-manager-interface/pom.xml
+++ b/vorgang-manager-interface/pom.xml
@@ -36,7 +36,7 @@
 
 	<groupId>de.ozgcloud.vorgang</groupId>
 	<artifactId>vorgang-manager-interface</artifactId>
-	<version>2.14.1</version>
+	<version>2.15.0-SNAPSHOT</version>
 
 	<name>OZG-Cloud Vorgang Manager gRPC Interface</name>
 	<description>Interface (gRPC) for Vorgang Manager Server</description>
diff --git a/vorgang-manager-server/pom.xml b/vorgang-manager-server/pom.xml
index 298fc329846b00f946bb8806398cd065fee0b123..6d3d42023647d383ba6f715c65cba0a629914ee3 100644
--- a/vorgang-manager-server/pom.xml
+++ b/vorgang-manager-server/pom.xml
@@ -38,7 +38,7 @@
 
 	<groupId>de.ozgcloud.vorgang</groupId>
 	<artifactId>vorgang-manager-server</artifactId>
-	<version>2.14.1</version>
+	<version>2.15.0-SNAPSHOT</version>
 
 	<name>OZG-Cloud Vorgang Manager Server</name>
 	<description>Server Implementierung des VorgangManagers</description>
@@ -50,15 +50,15 @@
 		<spring-boot.build-image.imageName>docker.ozg-sh.de/vorgang-manager:build-latest</spring-boot.build-image.imageName>
 
 		<ozgcloud.license.version>1.3.0</ozgcloud.license.version>
-		<zufi-manager-interface.version>1.0.0</zufi-manager-interface.version>
+		<zufi-manager-interface.version>1.4.0-SNAPSHOT</zufi-manager-interface.version>
 
-		<user-manager-interface.version>2.1.0</user-manager-interface.version>
-		<bescheid-manager.version>1.17.0</bescheid-manager.version>
+		<user-manager-interface.version>2.9.0-SNAPSHOT</user-manager-interface.version>
+		<bescheid-manager.version>1.18.0-SNAPSHOT</bescheid-manager.version>
 		<processor-manager.version>0.4.1</processor-manager.version>
-		<nachrichten-manager.version>2.11.0</nachrichten-manager.version>
-		<ozgcloud-starter.version>0.10.0</ozgcloud-starter.version>
-		<notification-manager.version>2.10.0</notification-manager.version>
-		<collaboration-manager.version>0.2.0</collaboration-manager.version>
+		<nachrichten-manager.version>2.12.0-SNAPSHOT</nachrichten-manager.version>
+		<ozgcloud-starter.version>0.12.0</ozgcloud-starter.version>
+		<notification-manager.version>2.11.0-SNAPSHOT</notification-manager.version>
+		<collaboration-manager.version>0.3.0-SNAPSHOT</collaboration-manager.version>
 
 		<zip.version>2.11.1</zip.version>
 		<jsoup.version>1.15.3</jsoup.version>
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerProperties.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..a17f844828bc8983610fab48bced19bbe373363d
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerProperties.java
@@ -0,0 +1,45 @@
+/*
+ * 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
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang;
+
+import jakarta.validation.constraints.NotBlank;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Validated
+@Configuration
+@ConfigurationProperties(prefix = "ozgcloud.application")
+public class VorgangManagerProperties {
+
+	@NotBlank
+	private String address;
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java
index cf991372cac1e53ef918bf360128a4939f9ccb6c..cc8905ccdc227a1c78533d54c0b26dea0fa71022 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java
@@ -75,7 +75,7 @@ class VorgangAttachedItemEventListener {
 		validateCreateCommand(command);
 
 		var item = mapper.fill(command.getBodyObject()).toBuilder().id(null).version(0).build();
-		service.create(command.getId(), item);
+		service.create(command, item);
 	}
 
 	void validateCreateCommand(Command command) {
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java
index 06aafc83380e42ac5d8ab5bdbd82ac5ff5f9914f..ef0d12da9202197c9c16570fe7005f8052f7a178 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java
@@ -31,6 +31,7 @@ import java.util.stream.Stream;
 
 import jakarta.validation.Valid;
 
+import org.apache.commons.collections.MapUtils;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
@@ -38,6 +39,9 @@ import org.springframework.validation.annotation.Validated;
 import de.ozgcloud.command.Command;
 import de.ozgcloud.command.CommandRevokeFailedEvent;
 import de.ozgcloud.command.CommandRevokedEvent;
+import de.ozgcloud.command.VorgangAttachedItemCreatedEvent;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.vorgang.command.PersistedCommand;
 import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -54,10 +58,10 @@ public class VorgangAttachedItemService {
 	private final VorgangAttachedItemRepository repository;
 	private final ApplicationEventPublisher publisher;
 
-	public VorgangAttachedItem create(@NonNull String commandId, @Valid VorgangAttachedItem item) {
+	public VorgangAttachedItem create(@NonNull Command command, @Valid VorgangAttachedItem item) {
 		var saved = repository.save(prepareForCreation(item));
 
-		publisher.publishEvent(new VorgangAttachedItemCreatedEvent(commandId, saved.getId()));
+		publisher.publishEvent(new VorgangAttachedItemCreatedEvent(buildExecutedCommand(command, saved), saved.getId()));
 
 		return saved;
 	}
@@ -71,11 +75,34 @@ public class VorgangAttachedItemService {
 	}
 
 	private Map<String, Object> removeId(@NonNull Map<String, Object> item) {
-		var map = new HashMap<String, Object>(item);
+		var map = new HashMap<>(item);
 		map.remove(VorgangAttachedItem.FIELDNAME_ID);
 		return Collections.unmodifiableMap(map);
 	}
 
+	Command buildExecutedCommand(Command command, VorgangAttachedItem item) {
+		return PersistedCommand.builder()
+				.id(command.getId())
+				.vorgangId(command.getVorgangId())
+				.relationId(command.getRelationId())
+				.relationVersion(command.getRelationVersion())
+				.order(command.getOrder())
+				.createdAt(command.getCreatedAt())
+				.createdBy(command.getCreatedBy())
+				.status(command.getStatus())
+				.createdResource(item.getId())
+				.bodyObject(buildBodyObject(item))
+				.build();
+	}
+
+	Map<String, Object> buildBodyObject(VorgangAttachedItem item) {
+		var map = new HashMap<String, Object>();
+		map.put(VorgangAttachedItem.FIELDNAME_ITEM_NAME, item.getItemName());
+		Optional.ofNullable(MapUtils.getString(item.getItem(), PostfachNachricht.FIELD_DIRECTION))
+				.ifPresent(direction -> map.put(PostfachNachricht.FIELD_DIRECTION, direction));
+		return Collections.unmodifiableMap(map);
+	}
+
 	public void update(String commandId, VorgangAttachedItem item) {
 		doUpdate(item.getId(), item.getVersion(), item.getItem());
 
@@ -160,7 +187,7 @@ public class VorgangAttachedItemService {
 	}
 
 	public void revokeCreate(Command command) {
-		handleRevoke(command, () -> delete(command.getRelationId(), command.getRelationVersion()));
+		handleRevoke(command, () -> delete(command.getCreatedResource(), command.getRelationVersion() + 1));
 	}
 
 	void delete(String id, long version) {
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java
index 9a6ebc1d3d61375724355556991d5af587a2d09b..5a4671ad54436d0e9657a7c62b323dbcaa25d0df 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java
@@ -31,8 +31,10 @@ import de.ozgcloud.command.CommandExecutedEvent;
 import de.ozgcloud.command.CommandFailedEvent;
 import de.ozgcloud.command.CommandRevokeFailedEvent;
 import de.ozgcloud.command.CommandRevokedEvent;
+import lombok.extern.log4j.Log4j2;
 
 @Component
+@Log4j2
 public class CommandEventListener {
 
 	@Autowired
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
index a9f57bac1d65ca9aba3af9671ab6d2efb2948558..dce3ec92f0c506bcabce138f6104003737adff39 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
@@ -36,11 +36,13 @@ import java.util.stream.Stream;
 
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.FindAndModifyOptions;
 import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.data.mongodb.core.aggregation.Aggregation;
 import org.springframework.data.mongodb.core.aggregation.ComparisonOperators.Eq;
+import org.springframework.data.mongodb.core.aggregation.ConditionalOperators;
 import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Switch;
 import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Switch.CaseOperator;
 import org.springframework.data.mongodb.core.aggregation.SetOperation;
@@ -261,17 +263,30 @@ class CommandRepository {
 		return query;
 	}
 
-	public Command setRevokeStatus(String id) {
-		return mongoOperations.findAndModify(queryById(id), buildUpdateStatusRevoke(), FindAndModifyOptions.options().returnNew(true), Command.class);
+	public Command setRevokeStatus(String id, String createdResource) {
+		return mongoOperations.findAndModify(queryById(id), buildUpdateStatusRevoke(createdResource), FindAndModifyOptions.options().returnNew(true),
+				Command.class);
 	}
 
-	private UpdateDefinition buildUpdateStatusRevoke() {
-		var switchOperation = Switch.switchCases(
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.NEW)).then(CommandStatus.CANCELED),
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.PENDING)).then(CommandStatus.REVOKE_PENDING),
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.FINISHED)).then(CommandStatus.REVOKE_PENDING))
+	private UpdateDefinition buildUpdateStatusRevoke(String createdResource) {
+		var setOperation = SetOperation.set(MONGODB_STATUS).toValue(buildSetStatusCondition());
+		if (StringUtils.isNotBlank(createdResource)) {
+			setOperation = setOperation.and().set(MONGODB_CREATED_RESOURCE).toValue(buildSetCreatedResourceCondition(createdResource));
+		}
+		return Aggregation.newUpdate(setOperation);
+	}
+
+	private Switch buildSetStatusCondition() {
+		return Switch.switchCases(
+						CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.NEW)).then(CommandStatus.CANCELED),
+						CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.PENDING)).then(CommandStatus.REVOKE_PENDING),
+						CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.FINISHED)).then(CommandStatus.REVOKE_PENDING))
 				.defaultTo(MONGODB_REFERENCE_STATUS);
-		return Aggregation.newUpdate(SetOperation.set(MONGODB_STATUS).toValue(switchOperation));
+	}
+
+	private ConditionalOperators.Cond buildSetCreatedResourceCondition(String createdResource) {
+		return ConditionalOperators.Cond.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.PENDING)).then(createdResource)
+				.otherwiseValueOf(MONGODB_CREATED_RESOURCE);
 	}
 
 	public Optional<Command> setRevokeStatusIfNotPending(String id) {
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
index 2f661a37b47f0da8143fdd5332e8385da4ecb1e5..ff7653e640230c195b26595b3b50c0589f305303 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
@@ -117,7 +117,7 @@ public class CommandService {
 	public void setCommandFinished(String commandId, String createdResource) {
 		var command = getById(commandId);
 		if (shouldRevoke(command)) {
-			repository.setRevokeStatus(commandId);
+			command = repository.setRevokeStatus(commandId, createdResource);
 			publishRevokeCommandEvent(command);
 			return;
 		}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachType.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachType.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b89cdfa416e725bbe8f5539579a05dfe3adab70
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachType.java
@@ -0,0 +1,50 @@
+package de.ozgcloud.vorgang.common.migration;
+
+import java.util.Set;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+
+import io.mongock.api.annotations.ChangeUnit;
+import io.mongock.api.annotations.Execution;
+import io.mongock.api.annotations.RollbackExecution;
+
+@ChangeUnit(id = "2024-09-14 15:00:00 OZG-6641", order = "M012", author = "ebardin", runAlways = true)
+public class M012_UpdateBayernIdPostfachType { // NOSONAR
+
+	static final String KEY_HEADER_SERVICE_KONTO_TYPE = "header.serviceKonto.type";
+	static final String KEY_EINGANG_SERVICE_KONTO_TYPE = "eingangs." + KEY_HEADER_SERVICE_KONTO_TYPE;
+	static final Set<String> POSSIBLE_BAYERN_ID_TYPE = Set.of("BayernId", "BayernID");
+	static final String BAYERN_ID_TYPE_NEW = "BAYERN_ID";
+	private static final String VORGANG_COLLECTION = "vorgang";
+
+	@Execution
+	public void doMigration(MongoTemplate template) {
+		updateVorgangHeader(template);
+		updateEingangsHeader(template);
+	}
+
+	private void updateVorgangHeader(MongoTemplate template) {
+		template.updateMulti(createFilterQuery(KEY_HEADER_SERVICE_KONTO_TYPE), createUpdate(KEY_HEADER_SERVICE_KONTO_TYPE), VORGANG_COLLECTION);
+	}
+
+	private void updateEingangsHeader(MongoTemplate template) {
+		template.updateMulti(createFilterQuery(KEY_EINGANG_SERVICE_KONTO_TYPE), createUpdate("eingangs.$[]." + KEY_HEADER_SERVICE_KONTO_TYPE),
+				VORGANG_COLLECTION);
+	}
+
+	private Query createFilterQuery(String key) {
+		return new Query(Criteria.where(key).in(POSSIBLE_BAYERN_ID_TYPE));
+	}
+
+	private Update createUpdate(String key) {
+		return new Update().set(key, BAYERN_ID_TYPE_NEW);
+	}
+
+	@RollbackExecution
+	public void rollback() {
+		// kein rollback implementiert
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java
index c844c3f36cc550abab150590103780d6b28bdc84..3e15c4de420cec0b23cf9338e795816acd9fc705 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java
@@ -24,8 +24,6 @@
 package de.ozgcloud.vorgang.common.search;
 
 import java.text.MessageFormat;
-import java.util.Collections;
-import java.util.HashMap;
 
 import org.apache.commons.collections.MapUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -34,11 +32,11 @@ import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Component;
 
 import de.ozgcloud.command.Command;
+import de.ozgcloud.command.VorgangAssignedEvent;
 import de.ozgcloud.command.VorgangCreatedEvent;
 import de.ozgcloud.vorgang.command.CommandService;
 import de.ozgcloud.vorgang.status.StatusChangedEvent;
 import de.ozgcloud.vorgang.vorgang.SetAktenzeichenCompletedEvent;
-import de.ozgcloud.vorgang.vorgang.VorgangAssignedEvent;
 import de.ozgcloud.vorgang.vorgang.VorgangDeletedEvent;
 import de.ozgcloud.vorgang.vorgang.VorgangService;
 import lombok.extern.log4j.Log4j2;
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java
index b7e0a3b89913ecac2c47e1a9cc9e20649743b46a..8a32bc95d96fa69088182ce7e9627059d3609767 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java
@@ -2,11 +2,15 @@ package de.ozgcloud.vorgang.common.userconfig;
 
 import java.util.List;
 
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
 
+import lombok.RequiredArgsConstructor;
+
+@Service
+@RequiredArgsConstructor
 public class UserConfigService {
-	@Autowired
-	private UserConfigRemoteService userConfigRemoteService;
+
+	private final UserConfigRemoteService userConfigRemoteService;
 
 	public List<String> getSupportedOrganisationsEinheiten() {
 		return userConfigRemoteService.getSupportedOrganisationsEinheiten();
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java
index 171439dbfbd3f234b2b5801b322cb963379f7972..778f33bf0339e0bf0e0d08b9a2c5806498a37e33 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java
@@ -25,29 +25,34 @@ package de.ozgcloud.vorgang.registry;
 
 import java.util.concurrent.TimeUnit;
 
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.annotation.PostConstruct;
+
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Profile;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 import de.ozgcloud.vorgang.common.userconfig.UserConfigService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
 
-@Profile("!itcase")
 @Component
-@ConditionalOnProperty(prefix = "ozgcloud.vorgang-manager", name = { "address" })
+@ConditionalOnProperty(prefix = "ozgcloud.zufi-manager", name = { "address" })
 @Log4j2
+@RequiredArgsConstructor
 class RegistryScheduler {
-	@Autowired
-	private RegistryService registryService;
 
-	@Autowired
-	private UserConfigService userConfigService;
+	private final RegistryService registryService;
+
+	private final UserConfigService userConfigService;
+
+	@PostConstruct
+	void logInitialization() {
+		LOG.info("Starting ZuFi registry scheduler");
+	}
 
-	@Scheduled(fixedDelayString = "${ozgcloud.vorgang-manager.registry.scheduler.fixedDelay:5}", //
-			initialDelayString = "${ozgcloud.vorgang-manager.registry.scheduler.initialDelay:5}", //
+	@Scheduled(fixedDelayString = "${ozgcloud.registry.scheduler.fixedDelayMinutes}",
+			initialDelayString = "${ozgcloud.registry.scheduler.initialDelayMinutes}",
 			timeUnit = TimeUnit.MINUTES)
 	@SchedulerLock(name = "RegistryScheduler")
 	void register() {
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java
index e2e8475bf30d833e339a9f688503611b2569ff98..028946325fe06593c20f604a94abc1679a2a8d66 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java
@@ -1,43 +1,28 @@
 package de.ozgcloud.vorgang.registry;
 
 import java.util.List;
-import java.util.Optional;
 
-import org.apache.commons.collections4.CollectionUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Service;
 
+import de.ozgcloud.vorgang.VorgangManagerProperties;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Service
 @Log4j2
+@RequiredArgsConstructor
+@ConditionalOnProperty(prefix = "ozgcloud.zufi-manager", name = { "address" })
 class RegistryService {
-	@Value(value = "${ozgcloud.vorgang-manager.address:#{null}}")
-	private Optional<String> vorgangManagerAddress;
 
-	@Autowired
-	private ZufiRemoteService zufiRemoteService;
+	private final VorgangManagerProperties vorgangManagerProperties;
+	private final ZufiRemoteService zufiRemoteService;
 
 	public void registerVorgangManager(List<String> supportedOrganisationsEinheiten) {
-		try {
-			register(supportedOrganisationsEinheiten);
-		} catch (Exception e) {
-			LOG.error("Error registering this VorgangsManager.", e);
+		if (supportedOrganisationsEinheiten.isEmpty()) {
+			LOG.warn("Missing organisationseinheitenIds. Skipping registration.");
+			return;
 		}
-	}
-
-	private void register(List<String> supportedOrganisationsEinheiten) {
-		if (CollectionUtils.isNotEmpty(supportedOrganisationsEinheiten)) {
-			registerAddress(supportedOrganisationsEinheiten, vorgangManagerAddress);
-		} else {
-			LOG.warn("No OrganistationsEinheitenIds provided. Not registering this VorgangsManager");
-		}
-	}
-
-	void registerAddress(List<String> supportedOrganisationsEinheiten, Optional<String> vorgangManagerAddress) {
-		vorgangManagerAddress.ifPresentOrElse(address -> {
-			zufiRemoteService.registerVorgangManager(supportedOrganisationsEinheiten, address);
-		}, () -> LOG.error("Property ozgcloud.vorgang-manager.address not set. Not registering this VorgangsManager"));
+		zufiRemoteService.registerVorgangManager(supportedOrganisationsEinheiten, vorgangManagerProperties.getAddress());
 	}
 }
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java
index bc436dedd25d7bd9ee4ef1ad95f7cfffb1612e8b..aab5f17c1c67ebe61d6122fb13a3da561628ed6b 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java
@@ -2,25 +2,29 @@ package de.ozgcloud.vorgang.registry;
 
 import java.util.List;
 
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Service;
 
 import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor;
-import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationRequest;
-import de.ozgcloud.zufi.grpc.registration.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub;
+import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcVorgangManagerRegistrationRequest;
+import de.ozgcloud.zufi.grpc.organisationseinheit.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub;
 import lombok.NonNull;
 import lombok.extern.log4j.Log4j2;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @Log4j2
 @Service
+@ConditionalOnProperty(prefix = "ozgcloud.zufi-manager", name = { "address" })
 class ZufiRemoteService {
+
 	@GrpcClient("zufi-manager")
 	private VorgangManagerRegistrationServiceBlockingStub serviceStub;
 
 	public void registerVorgangManager(@NonNull List<String> organistationsEinheitenIds, String vorgangManagerAddress) {
-		boolean success = getServiceStub()
-				.register(buildRequest(organistationsEinheitenIds, vorgangManagerAddress)).getSuccess();
-		LOG.info("Register success: " + success);
+		var result = getServiceStub().register(buildRequest(organistationsEinheitenIds, vorgangManagerAddress));
+		if (!result.getSuccess()) {
+			LOG.warn("Registration failed: {}", result.getMessage());
+		}
 	}
 
 	private VorgangManagerRegistrationServiceBlockingStub getServiceStub() {
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
index 51e2ba9baad098db8ba6c73cd84f6ee75ddd8d1a..67678fb2648931db32733b0f3c113d43e0d87bc5 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
@@ -42,6 +42,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import de.ozgcloud.command.Command;
+import de.ozgcloud.command.VorgangAssignedEvent;
 import de.ozgcloud.command.VorgangCreatedEvent;
 import de.ozgcloud.vorgang.clientattribute.ClientAttributeMap;
 import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
diff --git a/vorgang-manager-server/src/main/resources/application-local.yml b/vorgang-manager-server/src/main/resources/application-local.yml
index 3c001700cf121f982f772d96606412189ad50db3..f6a467f4938cfac669d42e0bbf2c81cfd10d9eb4 100644
--- a/vorgang-manager-server/src/main/resources/application-local.yml
+++ b/vorgang-manager-server/src/main/resources/application-local.yml
@@ -43,6 +43,9 @@ grpc:
       enabled: false
 
 spring:
+  cloud:
+    config:
+      enabled: false
   data:
     mongodb:
       database: vorgang-manager-local
@@ -55,7 +58,12 @@ spring:
       '[mail.smtp.starttls.enable]': true
 
 ozgcloud:
+  administration:
+    sync:
+      enabled: false
   aktenzeichen: de.ozgcloud.vorgang.vorgang.AktenzeichenProviderEA
+  application:
+    address: http://localhost:9090
   notification:
     mail-from: ea@ozg-sh.de
   redirect:
@@ -64,7 +72,7 @@ ozgcloud:
     url: http://localhost:9092/migration/user
   user:
     cleanup:
-      cron: 0 */5 * * * *
+      cron: "-"
   feature:
     bescheid:
       enable-dummy-document-processor: true
diff --git a/vorgang-manager-server/src/main/resources/application.yml b/vorgang-manager-server/src/main/resources/application.yml
index 6784f1d84c27c3a9745a4eb3f978d175cb440eeb..7bf48c56cfe7b1d089dd2dc367d1b6bcdd25d09c 100644
--- a/vorgang-manager-server/src/main/resources/application.yml
+++ b/vorgang-manager-server/src/main/resources/application.yml
@@ -5,12 +5,14 @@ logging:
 
 mongock:
   runner-type: initializingbean
-  migration-scan-package: 
+  migration-scan-package:
     - de.ozgcloud.vorgang.common.migration
   enabled: true
   transactionEnabled: false
 
 spring:
+  config:
+    import: optional:configserver:${ozgcloud_administration_address}/configserver/
   application:
     name: OzgCloud_VorgangManager
   data:
@@ -28,7 +30,7 @@ grpc:
       address: self:self
       negotiationType: TLS
     user-manager:
-      negotiationType: TLS  
+      negotiationType: TLS
     email:
       address: self:self
       negotiationType: TLS
@@ -40,6 +42,8 @@ grpc:
     command-manager:
       address: self:self
       negotiationType: PLAINTEXT
+    zufi-manager:
+      negotiationType: TLS
 
   server:
     security:
@@ -68,10 +72,17 @@ management:
   endpoints:
     web:
       exposure:
-        include: health,prometheus
+        include: health,prometheus,refresh
 
 ozgcloud:
+  administration:
+    sync:
+      delay: 900_000
   production: false
+  registry:
+    scheduler:
+      fixedDelayMinutes: 5
+      initialDelayMinutes: 5
   osi:
     postfach:
       scheduler:
@@ -80,6 +91,8 @@ ozgcloud:
     mail-from: EA-Poststelle@itvsh.de
   notification:
     mail-from: hilfe@ozgcloud.support
+    wiedervorlageDueToday:
+      cron: "0 15 0 * * *"
   nachrichten-manager:
     address: self:self
     negotiation-type: plaintext
@@ -96,4 +109,4 @@ ozgcloud:
   user-manager:
     address: ${grpc.client.user-manager.address:false}
     negotiation-type: ${grpc.client.user-manager.negotiationType}
-    
+
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumITCase.java
index 61fc27b309e3d269706f3a8bd3c1fd74da19ff6e..1488e8f8dd4f1baef4b2831081ccd6a078a6ef36 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumITCase.java
@@ -181,7 +181,7 @@ class AntragraumITCase {
 			grpcService.findRueckfragen(
 					GrpcFindRueckfrageRequestTestFactory.createBuilder().setSamlToken(TestUtils.loadTextFile("SamlResponse.xml")).build(),
 					responseObserver);
-			verify(responseObserver).onNext(captor.capture());
+			verify(responseObserver, timeout(30000)).onNext(captor.capture());
 			return captor.getValue().getRueckfrageHeadList();
 		}
 	}
@@ -189,12 +189,13 @@ class AntragraumITCase {
 	private Vorgang createVorgang(TrustLevel trustLevel) {
 		return VorgangTestFactory.createBuilder()
 				.id(null)
+				.version(0)
 				.header(VorgangHeadTestFactory.createBuilder().serviceKonto(createBayernIdServiceKonto(trustLevel)).build())
 				.build();
 	}
 
 	private ServiceKonto createBayernIdServiceKonto(TrustLevel trustLevel) {
-		return ServiceKontoTestFactory.createBuilder().type("BayernID").trustLevel(trustLevel.getValue()).build();
+		return ServiceKontoTestFactory.createBuilder().type("BAYERN_ID").trustLevel(trustLevel.getValue()).build();
 	}
 
 	private VorgangAttachedItem createPostfachNachrichtVorgangAttachedItem(String vorgangId) {
@@ -219,7 +220,7 @@ class AntragraumITCase {
 				PostfachAddress.VERSION_FIELD, 1,
 				PostfachAddress.IDENTIFIER_FIELD,
 				Map.of(PostfachNachricht.FIELD_POSTFACH_ID, PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE),
-				PostfachAddress.SERVICEKONTO_TYPE_FIELD, "BayernID"));
+				PostfachAddress.SERVICEKONTO_TYPE_FIELD, "BAYERN_ID"));
 		return nachrichtItem;
 	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java
index 516b1ea807fd936a7d7c91b034f8bba505c02017..c609c9f7e9df3ea1e1ff757b819d6dcce45169a7 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java
@@ -23,14 +23,20 @@
  */
 package de.ozgcloud.nachrichten.postfach;
 
+import static org.awaitility.Awaitility.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Map;
 import java.util.Optional;
+import java.util.concurrent.TimeUnit;
 
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
 import org.mockito.Mock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
@@ -40,10 +46,14 @@ import org.springframework.context.ApplicationEventPublisher;
 
 import de.ozgcloud.command.Command;
 import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.VorgangAttachedItemCreatedEvent;
 import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.notification.user.UserNotificationEventListener;
 import de.ozgcloud.vorgang.VorgangManagerServerApplication;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
 import de.ozgcloud.vorgang.command.CommandService;
 import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
 import de.ozgcloud.vorgang.vorgang.VorgangService;
 
 @ITCase
@@ -65,6 +75,9 @@ class PostfachEventListenerITCase {
 	@MockBean
 	private CommandService commandService;
 
+	@MockBean
+	private UserNotificationEventListener userNotificationEventListener;
+
 	@Nested
 	class TestSendPostfachNachricht {
 
@@ -89,4 +102,54 @@ class PostfachEventListenerITCase {
 		}
 	}
 
+	@Nested
+	class TestOnIncomingPostfachNachrichtItemCreated {
+
+		private static final Command COMMAND = CommandTestFactory.createBuilder().order(Order.CREATE_ATTACHED_ITEM.name())
+				.bodyObject(Map.of(VorgangAttachedItem.FIELDNAME_ITEM_NAME, AttachedItemRemoteService.ITEM_NAME,
+						PostfachNachricht.FIELD_DIRECTION, "IN")).build();
+
+		@Test
+		void shouldCallListener() {
+			var event = new VorgangAttachedItemCreatedEvent(COMMAND, CommandTestFactory.CREATED_RESOURCE);
+
+			publisher.publishEvent(event);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener).onIncomingPostfachNachrichtItemCreated(event));
+		}
+
+		@DisplayName("should not call listener")
+		@ParameterizedTest(name = "on order {0}")
+		@EnumSource(value = Order.class, names = { "CREATE_ATTACHED_ITEM" }, mode = EnumSource.Mode.EXCLUDE)
+		void shouldNotCallListenerOnWrongOrder(Order order) {
+			var command = CommandTestFactory.createBuilder().order(order.name()).build();
+
+			publisher.publishEvent(new VorgangAttachedItemCreatedEvent(command, CommandTestFactory.CREATED_RESOURCE));
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener, never()).onIncomingPostfachNachrichtItemCreated(any()));
+		}
+
+		@DisplayName("should not call listener when not postfach mail item")
+		@Test
+		void shouldNotCallListenerOnWrongItem() {
+			var command = CommandTestFactory.createBuilder().order(Order.CREATE_ATTACHED_ITEM.name())
+					.bodyObject(Map.of(VorgangAttachedItem.FIELDNAME_ITEM_NAME, "not-postfach-mail-item")).build();
+
+			publisher.publishEvent(new VorgangAttachedItemCreatedEvent(command, CommandTestFactory.CREATED_RESOURCE));
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener, never()).onIncomingPostfachNachrichtItemCreated(any()));
+		}
+
+		@DisplayName("should not call listener when not incoming item")
+		@Test
+		void shouldNotCallListenerOnWrongDirection() {
+			var command = CommandTestFactory.createBuilder().order(Order.CREATE_ATTACHED_ITEM.name())
+					.bodyObject(Map.of(VorgangAttachedItem.FIELDNAME_ITEM_NAME, AttachedItemRemoteService.ITEM_NAME,
+							PostfachNachricht.FIELD_DIRECTION, "OUT")).build();
+
+			publisher.publishEvent(new VorgangAttachedItemCreatedEvent(command, CommandTestFactory.CREATED_RESOURCE));
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener, never()).onIncomingPostfachNachrichtItemCreated(any()));
+		}
+	}
 }
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java
index 1ef45402d363fe6e8a0a695dd349c88383f31773..fbae6587b954a7ec5313c997719bb4ceb03d97b2 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java
@@ -164,4 +164,5 @@ class VorgangAttachedItemEventListenerITCase {
 			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(service).revokeDelete(command));
 		}
 	}
+
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java
index 28611d93e880d5012906f5dc8da81aea4c5a2846..26b2c4ba13544fdaf44d06f89a12a5308a2b676a 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java
@@ -51,6 +51,7 @@ import org.springframework.context.ApplicationEventPublisher;
 
 import de.ozgcloud.command.Command;
 import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.command.VorgangAttachedItemCreatedEvent;
 import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
 import de.ozgcloud.vorgang.command.CommandService;
 import de.ozgcloud.vorgang.command.CommandTestFactory;
@@ -98,7 +99,7 @@ class VorgangAttachedItemEventListenerTest {
 			void withItem() {
 				listener.createItem(CommandCreatedEventTestFactory.create(command));
 
-				verify(service).create(eq(CommandTestFactory.ID), itemCaptor.capture());
+				verify(service).create(eq(command), itemCaptor.capture());
 				assertThat(itemCaptor.getValue()).usingRecursiveComparison()
 						.ignoringFields(VorgangAttachedItem.FIELDNAME_ID, VorgangAttachedItem.FIELDNAME_VERSION)
 						.isEqualTo(VorgangAttachedItemTestFactory.create());
@@ -108,7 +109,7 @@ class VorgangAttachedItemEventListenerTest {
 			void withIdAndVersionAsNull() {
 				listener.createItem(CommandCreatedEventTestFactory.create(command));
 
-				verify(service).create(eq(CommandTestFactory.ID), itemCaptor.capture());
+				verify(service).create(eq(command), itemCaptor.capture());
 				var item = itemCaptor.getValue();
 
 				assertThat(item.getId()).isNull();
@@ -496,4 +497,5 @@ class VorgangAttachedItemEventListenerTest {
 			verify(service).revokePatch(command, CommandTestFactory.PREVIOUS_STATE);
 		}
 	}
+
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemITCase.java
index cfaf9ff74c00daa0d1405a656fb898ce181a0256..ef465103f6ad9e81c6a4741bd581d40179b1d6aa 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemITCase.java
@@ -289,7 +289,8 @@ class VorgangAttachedItemITCase {
 		private Command createRevokeCommand() {
 			return CommandTestFactory.createBuilder().order(Order.CREATE_ATTACHED_ITEM.name())
 					.relationId(persistedItem.getId())
-					.relationVersion(persistedItem.getVersion())
+					.relationVersion(persistedItem.getVersion() - 1)
+					.createdResource(persistedItem.getId())
 					.bodyObject(VorgangAttachedItemTestFactory.asMap()).build();
 		}
 	}
@@ -298,11 +299,11 @@ class VorgangAttachedItemITCase {
 	@Nested
 	class TestRevokeUpdateItem {
 
-		private final Map<String, Object> createItem = Map.<String, Object>of("EntryToRecoverByRevokeKey", "EntryToRecoverByRevokeValue",
+		private final Map<String, Object> createItem = Map.of("EntryToRecoverByRevokeKey", "EntryToRecoverByRevokeValue",
 				VorgangAttachedItemTestFactory.ITEM_FIELD_NAME, VorgangAttachedItemTestFactory.ITEM_FIELD_STRING_VALUE);
 		private VorgangAttachedItem persistedItem;
 
-		private final Map<String, Object> updateItem = Map.<String, Object>of(
+		private final Map<String, Object> updateItem = Map.of(
 				VorgangAttachedItemTestFactory.ITEM_FIELD_NAME, "RevertByRevokeValue",
 				"NewToRemoveByRevokeKey", "NewToRemoveByRevokeValue");
 		private Command updatedCommand;
@@ -391,11 +392,11 @@ class VorgangAttachedItemITCase {
 	@Nested
 	class TestRevokePatchItem {
 
-		private final Map<String, Object> createItem = Map.<String, Object>of(VorgangAttachedItemTestFactory.ITEM_FIELD_NAME,
+		private final Map<String, Object> createItem = Map.of(VorgangAttachedItemTestFactory.ITEM_FIELD_NAME,
 				VorgangAttachedItemTestFactory.ITEM_FIELD_STRING_VALUE);
 		private VorgangAttachedItem persistedItem;
 
-		private final Map<String, Object> patchItem = Map.<String, Object>of(VorgangAttachedItemTestFactory.ITEM_FIELD_NAME, "UpdatedStringValue");
+		private final Map<String, Object> patchItem = Map.of(VorgangAttachedItemTestFactory.ITEM_FIELD_NAME, "UpdatedStringValue");
 		private Command patchedCommand;
 		private String vorgangId;
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java
index 6bafdceabe71af6f52b99993f7a89d309f612924..ca9b0e78ab82bf475d52383be1dbae940bb6e3fb 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java
@@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.ApplicationEventPublisher;
 
+import de.ozgcloud.command.Command;
 import de.ozgcloud.common.test.ITCase;
 import de.ozgcloud.vorgang.command.CommandTestFactory;
 
@@ -27,25 +28,28 @@ class VorgangAttachedItemServiceITCase {
 
 	@Nested
 	class TestCreate {
+
+		private static final Command COMMAND = CommandTestFactory.create();
+
 		@Test
 		void shouldDenyMissingClientName() {
 			var item = VorgangAttachedItemTestFactory.createBuilder().client(StringUtils.EMPTY).build();
 
-			assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item)).isInstanceOf(ConstraintViolationException.class);
+			assertThatThrownBy(() -> service.create(COMMAND, item)).isInstanceOf(ConstraintViolationException.class);
 		}
 
 		@Test
 		void shouldDenyMissingVorgangId() {
 			var item = VorgangAttachedItemTestFactory.createBuilder().vorgangId(StringUtils.EMPTY).build();
 
-			assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item)).isInstanceOf(ConstraintViolationException.class);
+			assertThatThrownBy(() -> service.create(COMMAND, item)).isInstanceOf(ConstraintViolationException.class);
 		}
 
 		@Test
 		void shouldDenyMissingItemName() {
 			var item = VorgangAttachedItemTestFactory.createBuilder().itemName(StringUtils.EMPTY).build();
 
-			assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item)).isInstanceOf(ConstraintViolationException.class);
+			assertThatThrownBy(() -> service.create(COMMAND, item)).isInstanceOf(ConstraintViolationException.class);
 		}
 	}
 }
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java
index 932e678e5585088726653434c5e55ee0210fc3a9..7447aa18488ebd0ed7406989214afbda377580da 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java
@@ -33,6 +33,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -46,6 +47,8 @@ import org.springframework.context.ApplicationEventPublisher;
 import de.ozgcloud.command.Command;
 import de.ozgcloud.command.CommandRevokeFailedEvent;
 import de.ozgcloud.command.CommandRevokedEvent;
+import de.ozgcloud.command.VorgangAttachedItemCreatedEvent;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
 import de.ozgcloud.vorgang.command.CommandTestFactory;
 import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
@@ -64,53 +67,205 @@ class VorgangAttachedItemServiceTest {
 	@Nested
 	class TestCreateItem {
 
+		private static final VorgangAttachedItem PREPARED_ITEM = VorgangAttachedItemTestFactory.create();
+		private static final VorgangAttachedItem PERSISTED_ITEM = VorgangAttachedItemTestFactory.createBuilder()
+				.id(CommandTestFactory.CREATED_RESOURCE).build();
+
+		@Captor
+		private ArgumentCaptor<VorgangAttachedItemCreatedEvent> eventCaptor;
+
+		@BeforeEach
+		void init() {
+			when(repository.save(any())).thenReturn(PERSISTED_ITEM);
+			doReturn(PREPARED_ITEM).when(service).prepareForCreation(any());
+		}
+
+		@Test
+		void shouldCallPrepareForCreation() {
+			var item = VorgangAttachedItemTestFactory.create();
+
+			service.create(CommandTestFactory.create(), item);
+
+			verify(service).prepareForCreation(item);
+		}
+
 		@Test
 		void shouldCallRepository() {
-			when(repository.save(any())).thenReturn(VorgangAttachedItemTestFactory.create());
+			service.create(CommandTestFactory.create(), VorgangAttachedItemTestFactory.create());
+
+			verify(repository).save(PREPARED_ITEM);
+		}
+
+		@Test
+		void shouldCallBuildExecutedCommand() {
+			var command = CommandTestFactory.create();
 
-			service.create(CommandTestFactory.ID, VorgangAttachedItemTestFactory.create());
+			service.create(command, VorgangAttachedItemTestFactory.create());
 
-			verify(repository).save(any());
+			verify(service).buildExecutedCommand(command, PERSISTED_ITEM);
 		}
 
 		@Test
 		void shouldPublishEvent() {
-			when(repository.save(any())).thenReturn(VorgangAttachedItemTestFactory.create());
+			var executedCommand = CommandTestFactory.create();
+			doReturn(executedCommand).when(service).buildExecutedCommand(any(), any());
 
-			service.create(CommandTestFactory.ID, VorgangAttachedItemTestFactory.create());
+			service.create(CommandTestFactory.create(), VorgangAttachedItemTestFactory.create());
 
-			verify(publisher).publishEvent(any(VorgangAttachedItemCreatedEvent.class));
+			verify(publisher).publishEvent(eventCaptor.capture());
+			assertThat(eventCaptor.getValue()).satisfies(event -> {
+				assertThat(event.getCommand()).isSameAs(executedCommand);
+				assertThat(event.getCreatedResource()).isEqualTo(CommandTestFactory.CREATED_RESOURCE);
+			});
 		}
+	}
 
-		@Nested
-		class TestPrepareForCreation {
-			@Test
-			void shouldRemoveId() {
-				var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
+	@Nested
+	class TestPrepareForCreation {
+		@Test
+		void shouldRemoveId() {
+			var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
 
-				assertThat(prepared.getId()).isNull();
-			}
+			assertThat(prepared.getId()).isNull();
+		}
 
-			@Test
-			void shouldSetVersionToZero() {
-				var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
+		@Test
+		void shouldSetVersionToZero() {
+			var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
 
-				assertThat(prepared.getVersion()).isZero();
-			}
+			assertThat(prepared.getVersion()).isZero();
+		}
 
-			@Test
-			void shouldRemoveIdFromItem() {
-				var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
+		@Test
+		void shouldRemoveIdFromItem() {
+			var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
 
-				assertThat(prepared.getItem()).doesNotContainKey(VorgangAttachedItem.FIELDNAME_ID);
-			}
+			assertThat(prepared.getItem()).doesNotContainKey(VorgangAttachedItem.FIELDNAME_ID);
+		}
 
-			@Test
-			void shouldSetIsDeletedToFalse() {
-				var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
+		@Test
+		void shouldSetIsDeletedToFalse() {
+			var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
 
-				assertThat(prepared.isDeleted()).isFalse();
-			}
+			assertThat(prepared.isDeleted()).isFalse();
+		}
+	}
+
+	@Nested
+	class TestBuildExecutedCommand {
+
+		private static final VorgangAttachedItem ITEM = VorgangAttachedItemTestFactory.create();
+
+		@Test
+		void shouldSetId() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getId()).isEqualTo(CommandTestFactory.ID);
+		}
+
+		@Test
+		void shouldSetVorgangId() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getVorgangId()).isEqualTo(VorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldSetRelationId() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
+		}
+
+		@Test
+		void shouldSetRelationVersion() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION);
+		}
+
+		@Test
+		void shouldSetOrder() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getOrder()).isEqualTo(CommandTestFactory.ORDER.name());
+		}
+
+		@Test
+		void shouldSetCreatedAt() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getCreatedAt()).isEqualTo(CommandTestFactory.CREATED_AT);
+		}
+
+		@Test
+		void shouldSetCreatedBy() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getCreatedBy()).isEqualTo(CommandTestFactory.CREATED_BY);
+		}
+
+		@Test
+		void shouldSetStatus() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getStatus()).isEqualTo(CommandTestFactory.STATUS);
+		}
+
+		@Test
+		void shouldSetCreatedResource() {
+			var result = buildExecutedCommand();
+
+			assertThat(result.getCreatedResource()).isEqualTo(VorgangAttachedItemTestFactory.ID);
+		}
+
+		@Test
+		void shouldCallBuildBodyObject() {
+			buildExecutedCommand();
+
+			verify(service).buildBodyObject(ITEM);
+		}
+
+		@Test
+		void shouldSetBodyObject() {
+			var bodyObject = Map.<String, Object>of("key", "value");
+			doReturn(bodyObject).when(service).buildBodyObject(any());
+
+			var result = buildExecutedCommand();
+
+			assertThat(result.getBodyObject()).isEqualTo(bodyObject);
+		}
+
+		private Command buildExecutedCommand() {
+			return service.buildExecutedCommand(CommandTestFactory.create(), ITEM);
+		}
+	}
+
+	@Nested
+	class TestBuildBodyObject {
+
+		@Test
+		void shouldSetItemName() {
+			var result = service.buildBodyObject(VorgangAttachedItemTestFactory.create());
+
+			assertThat(result).containsEntry(VorgangAttachedItem.FIELDNAME_ITEM_NAME, ITEM_NAME);
+		}
+
+		@Test
+		void shouldSetMailDirection() {
+			var item = VorgangAttachedItemTestFactory.createBuilder()
+					.item(Map.of(PostfachNachricht.FIELD_DIRECTION, PostfachNachricht.Direction.IN.name())).build();
+
+			var result = service.buildBodyObject(item);
+
+			assertThat(result).containsEntry(PostfachNachricht.FIELD_DIRECTION, PostfachNachricht.Direction.IN.name());
+		}
+
+		@Test
+		void shouldHandleMissingDirection() {
+			var result = service.buildBodyObject(VorgangAttachedItemTestFactory.create());
+
+			assertThat(result).doesNotContainKey(PostfachNachricht.FIELD_DIRECTION);
 		}
 	}
 
@@ -361,7 +516,7 @@ class VorgangAttachedItemServiceTest {
 	@Nested
 	class TestRevokeCreate {
 
-		private final Command command = CommandTestFactory.create();
+		private final Command command = CommandTestFactory.createBuilder().createdResource(CommandTestFactory.CREATED_RESOURCE).build();
 
 		@Test
 		void shouldCallHandleRevoke() {
@@ -374,7 +529,7 @@ class VorgangAttachedItemServiceTest {
 		void shouldCallDelete() {
 			service.revokeCreate(command);
 
-			verify(service).delete(CommandTestFactory.RELATION_ID, CommandTestFactory.RELATION_VERSION);
+			verify(service).delete(CommandTestFactory.CREATED_RESOURCE, CommandTestFactory.RELATION_VERSION + 1);
 		}
 	}
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/collaboration/CollaborationITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/collaboration/CollaborationITCase.java
index 32db2a67bebf61625a2e5eea835a61eaa5c87665..3a1508c570ac7a6ac3bd1e41fe1815041e1541e6 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/collaboration/CollaborationITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/collaboration/CollaborationITCase.java
@@ -24,7 +24,6 @@
 package de.ozgcloud.vorgang.collaboration;
 
 import static org.assertj.core.api.Assertions.*;
-import static org.assertj.core.api.InstanceOfAssertFactories.*;
 import static org.awaitility.Awaitility.*;
 import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.ArgumentMatchers.*;
@@ -41,6 +40,8 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
@@ -60,7 +61,11 @@ import de.ozgcloud.collaboration.CollaborationServiceGrpc.CollaborationServiceBl
 import de.ozgcloud.collaboration.GrpcGetFileContentRequest;
 import de.ozgcloud.command.Command;
 import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.nachrichten.postfach.PostfachAddress;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.PostfachRemoteService;
 import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
 import de.ozgcloud.vorgang.callcontext.CallContext;
 import de.ozgcloud.vorgang.callcontext.TestCallContextAttachingInterceptor;
@@ -71,6 +76,7 @@ import de.ozgcloud.vorgang.command.CreateCommandRequest;
 import de.ozgcloud.vorgang.files.FileService;
 import de.ozgcloud.vorgang.files.GridFsTestFactory;
 import de.ozgcloud.vorgang.files.OzgFileTestFactory;
+import de.ozgcloud.vorgang.servicekonto.PostfachAddressTestFactory;
 import de.ozgcloud.vorgang.vorgang.Vorgang;
 import de.ozgcloud.vorgang.vorgang.VorgangHead;
 import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
@@ -89,6 +95,10 @@ import net.devh.boot.grpc.client.inject.GrpcClient;
 @DirtiesContext
 class CollaborationITCase {
 
+	private static final String FIELD_COLLABORATION_VORGANG_ID = "collaborationVorgangId";
+	private static final String TITEL = "Collaboration Vorgang";
+	private static final String ANFRAGE = "Anfrage";
+
 	@Autowired
 	private CommandService commandService;
 
@@ -97,85 +107,21 @@ class CollaborationITCase {
 
 	@MockBean
 	private OzgCloudUserProfileService ozgCloudUserProfileService;
+	@MockBean
+	private PostfachRemoteService postfachRemoteService;
 
 	@Mock
 	private OzgCloudUserProfile ozgCloudUserProfile;
 
-	@Nested
-	class TestCreateCollaborationVorgang {
+	private String vorgangId;
 
-		@BeforeEach
-		void init() {
-			mongoOperations.dropCollection(Command.class);
-			mongoOperations.dropCollection(Vorgang.class);
-			mongoOperations.dropCollection(VorgangAttachedItem.class);
-			when(ozgCloudUserProfile.getId()).thenReturn(OzgCloudUserId.from(CommandTestFactory.CREATED_BY));
-			when(ozgCloudUserProfileService.getById(any())).thenReturn(ozgCloudUserProfile);
-
-			vorgangId = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).build()).getId();
-		}
-
-		private static final String FIELD_COLLABORATION_VORGANG_ID = "collaborationVorgangId";
-		private static final String TITEL = "Collaboration Vorgang";
-		private static final String ANFRAGE = "Anfrage";
-
-		private String vorgangId;
-
-		@Test
-		void shouldSetCollaborationVorgangId() {
-			var command = commandService.createCommand(buildCreateCollaborationVorgangCommand(vorgangId));
+	@BeforeEach
+	void init() {
+		mongoOperations.dropCollection(Command.class);
+		mongoOperations.dropCollection(Vorgang.class);
+		mongoOperations.dropCollection(VorgangAttachedItem.class);
 
-			waitUntilCommandFinished(command.getId());
-
-			var collaborationRequests = loadCollaborationRequest(vorgangId);
-			assertThat(collaborationRequests).hasSize(1).first().extracting(VorgangAttachedItem::getItem, MAP)
-					.containsKey(FIELD_COLLABORATION_VORGANG_ID);
-		}
-
-		@Test
-		void shouldCreateCollaborationVorgang() {
-			var command = commandService.createCommand(buildCreateCollaborationVorgangCommand(vorgangId));
-
-			waitUntilCommandFinished(command.getId());
-
-			var collaborationVorgang = loadCollaborationVorgang(vorgangId);
-			assertThat(collaborationVorgang.getHeader()).extracting(VorgangHead::getCollaborationLevel)
-					.isEqualTo(CreateCollaborationVorgangRequestTestFactory.COLLABORATION_LEVEL);
-			assertThat(collaborationVorgang.getHeader()).extracting(VorgangHead::getOrganisationsEinheitId)
-					.isEqualTo(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
-			assertThat(collaborationVorgang.getClientAttributes()).isEmpty();
-		}
-
-		private CreateCommandRequest buildCreateCollaborationVorgangCommand(String vorgangId) {
-			return CreateCommandRequest.builder()
-					.callContext(CallContext.builder().client("test").build())
-					.vorgangId(vorgangId)
-					.relationId(vorgangId)
-					.order("CREATE_COLLABORATION_REQUEST")
-					.bodyObject(Map.of(
-							"titel", TITEL,
-							"anfrage", ANFRAGE,
-							"zustaendigeStelle", ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID))
-					.build();
-		}
-
-		private void waitUntilCommandFinished(String commandId) {
-			await().atMost(60, TimeUnit.SECONDS).until(
-					() -> mongoOperations.findById(commandId, Command.class),
-					command -> command.getStatus() == CommandStatus.FINISHED);
-		}
-
-		private Vorgang loadCollaborationVorgang(String sourceVorgangId) {
-			var collaborationVorgangId = loadCollaborationRequest(sourceVorgangId).getFirst().getItem().get(FIELD_COLLABORATION_VORGANG_ID);
-			return mongoOperations.findById(collaborationVorgangId, Vorgang.class);
-		}
-
-		private List<VorgangAttachedItem> loadCollaborationRequest(String vorgangId) {
-			var query = new Query(new Criteria().andOperator(
-					Criteria.where(VorgangAttachedItem.FIELDNAME_VORGANG_ID).is(vorgangId),
-					Criteria.where(VorgangAttachedItem.FIELDNAME_ITEM_NAME).is("CollaborationRequest")));
-			return mongoOperations.find(query, VorgangAttachedItem.class);
-		}
+		vorgangId = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0L).build()).getId();
 	}
 
 	@DisplayName("Get file content")
@@ -244,4 +190,121 @@ class CollaborationITCase {
 			return collaborationStub.withInterceptors(new TestCallContextAttachingInterceptor());
 		}
 	}
+
+	private CreateCommandRequest buildCreateCollaborationVorgangCommand(String vorgangId, int collaborationLevel) {
+		return CreateCommandRequest.builder()
+				.callContext(CallContext.builder().client("test").build())
+				.vorgangId(vorgangId)
+				.relationId(vorgangId)
+				.order("CREATE_COLLABORATION_REQUEST")
+				.bodyObject(Map.of(
+						"titel", TITEL,
+						"anfrage", ANFRAGE,
+						"collaborationLevel", collaborationLevel,
+						"zustaendigeStelle", ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID))
+				.build();
+	}
+
+	private List<VorgangAttachedItem> loadCollaborationRequest(String vorgangId) {
+		var query = new Query(new Criteria().andOperator(
+				Criteria.where(VorgangAttachedItem.FIELDNAME_VORGANG_ID).is(vorgangId),
+				Criteria.where(VorgangAttachedItem.FIELDNAME_ITEM_NAME).is("CollaborationRequest")));
+		return mongoOperations.find(query, VorgangAttachedItem.class);
+	}
+
+	private void waitUntilCommandHasStatus(String commandId, CommandStatus status) {
+		await().atMost(60, TimeUnit.SECONDS).until(
+				() -> mongoOperations.findById(commandId, Command.class),
+				command -> command.getStatus() == status);
+	}
+
+	@Nested
+	class TestCreateCollaborationVorgang {
+
+		@BeforeEach
+		void init() {
+			when(ozgCloudUserProfile.getId()).thenReturn(OzgCloudUserId.from(CommandTestFactory.CREATED_BY));
+			when(ozgCloudUserProfileService.getById(any())).thenReturn(ozgCloudUserProfile);
+		}
+
+		@Test
+		void shouldSetCollaborationVorgangId() {
+			var command = commandService.createCommand(
+					buildCreateCollaborationVorgangCommand(vorgangId, CreateCollaborationVorgangRequestTestFactory.COLLABORATION_LEVEL));
+
+			waitUntilCommandHasStatus(command.getId(), CommandStatus.FINISHED);
+
+			var collaborationRequests = loadCollaborationRequest(vorgangId);
+			assertThat(collaborationRequests).hasSize(1).first().extracting(VorgangAttachedItem::getItem, MAP)
+					.containsKey(FIELD_COLLABORATION_VORGANG_ID);
+		}
+
+		@Test
+		void shouldCreateCollaborationVorgang() {
+			var command = commandService.createCommand(
+					buildCreateCollaborationVorgangCommand(vorgangId, CreateCollaborationVorgangRequestTestFactory.COLLABORATION_LEVEL));
+
+			waitUntilCommandHasStatus(command.getId(), CommandStatus.FINISHED);
+
+			var collaborationVorgang = loadCollaborationVorgang(vorgangId);
+			assertThat(collaborationVorgang.getHeader()).extracting(VorgangHead::getCollaborationLevel)
+					.isEqualTo(CreateCollaborationVorgangRequestTestFactory.COLLABORATION_LEVEL);
+			assertThat(collaborationVorgang.getHeader()).extracting(VorgangHead::getOrganisationsEinheitId)
+					.isEqualTo(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
+			assertThat(collaborationVorgang.getClientAttributes()).isEmpty();
+		}
+
+		private Vorgang loadCollaborationVorgang(String sourceVorgangId) {
+			var collaborationVorgangId = loadCollaborationRequest(sourceVorgangId).getFirst().getItem().get(FIELD_COLLABORATION_VORGANG_ID);
+			return mongoOperations.findById(collaborationVorgangId, Vorgang.class);
+		}
+
+	}
+
+	@Nested
+	class TestCreateFachstellenBeteiligungRequest {
+
+		private static final int COLLABORATION_LEVEL = 4;
+
+		@Captor
+		private ArgumentCaptor<PostfachNachricht> postfachNachrichtCaptor;
+
+		@BeforeEach
+		void init() {
+			when(ozgCloudUserProfile.getId()).thenReturn(OzgCloudUserId.from(CommandTestFactory.CREATED_BY));
+			when(ozgCloudUserProfileService.getById(any())).thenReturn(ozgCloudUserProfile);
+		}
+
+		@Test
+		void shouldCreateCollaborationRequest() {
+			var command = commandService.createCommand(buildCreateCollaborationVorgangCommand(vorgangId, COLLABORATION_LEVEL));
+
+			waitUntilCommandHasStatus(command.getId(), CommandStatus.FINISHED);
+
+			var collaborationRequests = loadCollaborationRequest(vorgangId);
+			assertThat(collaborationRequests).hasSize(1).first().extracting(VorgangAttachedItem::getItem, MAP)
+					.containsEntry(FIELD_COLLABORATION_VORGANG_ID, vorgangId);
+		}
+
+		@Test
+		void shouldSendPostfachNachricht() {
+			var command = commandService.createCommand(buildCreateCollaborationVorgangCommand(vorgangId, COLLABORATION_LEVEL));
+
+			waitUntilCommandHasStatus(command.getId(), CommandStatus.FINISHED);
+
+			verify(postfachRemoteService).sendMessage(postfachNachrichtCaptor.capture());
+			assertThat(postfachNachrichtCaptor.getValue().getPostfachAddress()).extracting(PostfachAddress::getIdentifier)
+					.hasToString(PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE);
+		}
+
+		@Test
+		void shouldDeleteCollaborationRequest() {
+			doThrow(TechnicalException.class).when(postfachRemoteService).sendMessage(any());
+			var command = commandService.createCommand(buildCreateCollaborationVorgangCommand(vorgangId, COLLABORATION_LEVEL));
+
+			waitUntilCommandHasStatus(command.getId(), CommandStatus.ERROR);
+
+			assertThat(loadCollaborationRequest(vorgangId)).isEmpty();
+		}
+	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java
index 6f99e9b91bef7f1664e80194b2755173a0c1da37..106c571385c18760a91d1198d34993944a08704d 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java
@@ -92,21 +92,20 @@ class CommandRepositoryITCase {
 	@Nested
 	class TestFinishCommand {
 
-		@BeforeEach
-		void init() {
-			mongoOperations.dropCollection(PersistedCommand.COLLECTION_NAME);
-		}
-
 		@DisplayName("should update status to finished")
 		@ParameterizedTest(name = "with status {0}")
 		@EnumSource(value = CommandStatus.class, names = { "PENDING", "REVOKE_PENDING" })
 		void shouldUpdateStatusToFinished(CommandStatus commandStatus) {
-			var command = mongoOperations.save(CommandTestFactory.createBuilder().id(null).status(commandStatus).build());
+			var command = mongoOperations.save(CommandTestFactory.createBuilder().id(null).status(commandStatus)
+					.createdResource(CommandTestFactory.CREATED_RESOURCE).build());
 
 			repository.finishCommand(command.getId());
 
 			var result = repository.findById(command.getId());
-			assertThat(result).isPresent().get().extracting(Command::getStatus).isEqualTo(CommandStatus.FINISHED);
+			assertThat(result).isPresent().get().satisfies(cmd -> {
+				assertThat(cmd.getStatus()).isEqualTo(CommandStatus.FINISHED);
+				assertThat(cmd.getCreatedResource()).isEqualTo(CommandTestFactory.CREATED_RESOURCE);
+			});
 		}
 
 		@DisplayName("should update status to finished")
@@ -322,7 +321,7 @@ class CommandRepositoryITCase {
 			}
 
 			@Test
-			// TODO schreibe ein Testcase für Order, Status und Zeit
+				// TODO schreibe ein Testcase für Order, Status und Zeit
 			void shouldFindCommand() {
 				var command = repository.save(createCommandBuilder()
 						.status(CommandStatus.FINISHED)
@@ -483,7 +482,7 @@ class CommandRepositoryITCase {
 		@Test
 		void shouldReturnParentId() {
 			var commandId = mongoOperations.save(
-					CommandTestFactory.createBuilder().id(null).bodyObject(Map.of(PersistedCommand.PROPERTY_PARENT_ID, PARENT_ID)).build())
+							CommandTestFactory.createBuilder().id(null).bodyObject(Map.of(PersistedCommand.PROPERTY_PARENT_ID, PARENT_ID)).build())
 					.getId();
 
 			var parentId = repository.getParentId(commandId);
@@ -615,30 +614,39 @@ class CommandRepositoryITCase {
 		void shouldSetCanceled() {
 			var command = mongoOperations.save(CommandTestFactory.createBuilder().id(null).status(CommandStatus.NEW).build());
 
-			repository.setRevokeStatus(command.getId());
+			setRevokeStatus(command.getId());
 
 			var result = repository.findById(command.getId());
-			assertThat(result).isPresent().get().extracting(Command::getStatus).isEqualTo(CommandStatus.CANCELED);
+			assertThat(result).isPresent().get().satisfies(cmd -> {
+				assertThat(cmd.getStatus()).isEqualTo(CommandStatus.CANCELED);
+				assertThat(cmd.getCreatedResource()).isBlank();
+			});
 		}
 
 		@Test
 		void shouldSetRevokePendingWhenPending() {
 			var command = mongoOperations.save(CommandTestFactory.createBuilder().id(null).build());
 
-			repository.setRevokeStatus(command.getId());
+			setRevokeStatus(command.getId());
 
 			var result = repository.findById(command.getId());
-			assertThat(result).isPresent().get().extracting(Command::getStatus).isEqualTo(CommandStatus.REVOKE_PENDING);
+			assertThat(result).isPresent().get().satisfies(cmd -> {
+				assertThat(cmd.getStatus()).isEqualTo(CommandStatus.REVOKE_PENDING);
+				assertThat(cmd.getCreatedResource()).isEqualTo(CommandTestFactory.CREATED_RESOURCE);
+			});
 		}
 
 		@Test
 		void shouldSetRevokePendingWhenFinished() {
 			var command = mongoOperations.save(CommandTestFactory.createBuilder().id(null).status(CommandStatus.FINISHED).build());
 
-			repository.setRevokeStatus(command.getId());
+			setRevokeStatus(command.getId());
 
 			var result = repository.findById(command.getId());
-			assertThat(result).isPresent().get().extracting(Command::getStatus).isEqualTo(CommandStatus.REVOKE_PENDING);
+			assertThat(result).isPresent().get().satisfies(cmd -> {
+				assertThat(cmd.getStatus()).isEqualTo(CommandStatus.REVOKE_PENDING);
+				assertThat(cmd.getCreatedResource()).isBlank();
+			});
 		}
 
 		@DisplayName("should not update when")
@@ -647,10 +655,17 @@ class CommandRepositoryITCase {
 		void shouldNotUpdate(CommandStatus status) {
 			var command = mongoOperations.save(CommandTestFactory.createBuilder().id(null).status(status).build());
 
-			repository.setRevokeStatus(command.getId());
+			setRevokeStatus(command.getId());
 
 			var result = repository.findById(command.getId());
-			assertThat(result).isPresent().get().extracting(Command::getStatus).isEqualTo(status);
+			assertThat(result).isPresent().get().satisfies(cmd -> {
+				assertThat(cmd.getStatus()).isEqualTo(status);
+				assertThat(cmd.getCreatedResource()).isNull();
+			});
+		}
+
+		private void setRevokeStatus(String commandId) {
+			repository.setRevokeStatus(commandId, CommandTestFactory.CREATED_RESOURCE);
 		}
 	}
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
index 85714d30f81e92ba77ce0c7f575e89dcc04343fa..3f4d68d90efa91280762ec75d49a7692d352a175 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
@@ -214,10 +214,12 @@ class CommandServiceTest {
 		@Nested
 		class TestRevokePendingCommand {
 
-			private static final Command REVOKE_PENDING_COMMAND = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build();
+			private static final Command REVOKE_PENDING_COMMAND = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING)
+					.createdResource(CommandTestFactory.CREATED_RESOURCE).build();
 
 			@BeforeEach
 			void init() {
+				when(repository.setRevokeStatus(anyString(), anyString())).thenReturn(REVOKE_PENDING_COMMAND);
 				doReturn(true).when(service).shouldRevoke(any());
 				doReturn(REVOKE_PENDING_COMMAND).when(service).getById(anyString());
 			}
@@ -233,7 +235,7 @@ class CommandServiceTest {
 			void shouldCallRepository() {
 				setCommandFinished();
 
-				verify(repository).setRevokeStatus(CommandTestFactory.ID);
+				verify(repository).setRevokeStatus(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
 			}
 
 			@Test
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java
index 7df40567d8e858171053fe352454a7e67decde01..e890e4ea2097781bba11e16db414d51370c90562 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java
@@ -168,7 +168,7 @@ class GrpcCommandServiceITCase {
 			mongoOperations.dropCollection(Command.COLLECTION_NAME);
 			mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
 
-			vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).build());
+			vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).version(0).build());
 			when(readIsPermitted.test(any())).thenReturn(true);
 
 			parentCommand = createParentCommand();
@@ -259,9 +259,5 @@ class GrpcCommandServiceITCase {
 			return mongoOperations.findById(grpcCommand.getId(), Command.class);
 		}
 
-		private void assertCommandIsFinished(GrpcCommand grpcCommand) {
-			var command = mongoOperations.findById(grpcCommand.getId(), Command.class);
-			assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED);
-		}
 	}
 }
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachTypeITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachTypeITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..546eb8da689160432261bef9bb4a08f4d7f577d8
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachTypeITCase.java
@@ -0,0 +1,137 @@
+/*
+ * 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
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.List;
+import java.util.Map;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M012_UpdateBayernIdPostfachTypeITCase {
+
+	private static final String FIELD_HEADER = "header";
+	private static final String FIELD_SERVICE_KONTO = "serviceKonto";
+	private static final String FIELD_TYPE = "type";
+	private static final String FIELD_EINGANG = "eingangs";
+
+	private final M012_UpdateBayernIdPostfachType migration = new M012_UpdateBayernIdPostfachType();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoTemplate template;
+
+	@BeforeEach
+	void init() {
+		dbTestUtils.dropVorgangCollection();
+	}
+
+	@DisplayName("should migrate when")
+	@ParameterizedTest(name = "header's serviceKonto type is \"{0}\"")
+	@ValueSource(strings = { "BayernId", "BayernID" })
+	void shouldMitgrateHeader(String type) {
+		saveVorgangWithHeaderServiceKonto(createServiceKonto(type));
+
+		migration.doMigration(template);
+
+		assertThat(loadHeaderServiceKonto()).containsEntry(FIELD_TYPE, M012_UpdateBayernIdPostfachType.BAYERN_ID_TYPE_NEW);
+	}
+
+	@DisplayName("should migrate when")
+	@ParameterizedTest(name = "eingang's serviceKonto type is \"{0}\"")
+	@ValueSource(strings = { "BayernId", "BayernID" })
+	void shouldMigrateEingang(String type) {
+		saveVorgangWithEingangServiceKonto(createServiceKonto(type));
+
+		migration.doMigration(template);
+
+		assertThat(loadEingangServiceKonto()).containsEntry(FIELD_TYPE, M012_UpdateBayernIdPostfachType.BAYERN_ID_TYPE_NEW);
+	}
+
+	@DisplayName("should skip when")
+	@ParameterizedTest(name = "header's serviceKonto type is \"{0}\"")
+	@NullAndEmptySource
+	@ValueSource(strings = { "another", "OSI" })
+	void shouldSkipWhenServiceKontoMissingInHeader(String type) {
+		saveVorgangWithHeaderServiceKonto(createServiceKonto(type));
+
+		migration.doMigration(template);
+
+		assertThat(loadHeaderServiceKonto()).containsEntry(FIELD_TYPE, type);
+	}
+
+	@DisplayName("should skip when")
+	@ParameterizedTest(name = "eingang's serviceKonto type is \"{0}\"")
+	@NullAndEmptySource
+	@ValueSource(strings = { "another", "OSI" })
+	void shouldSkipWhenServiceKontoMissingInEingang(String type) {
+		saveVorgangWithEingangServiceKonto(createServiceKonto(type));
+
+		migration.doMigration(template);
+
+		assertThat(loadEingangServiceKonto()).containsEntry(FIELD_TYPE, type);
+	}
+
+	private Document createServiceKonto(String type) {
+		var serviceKonto = new Document();
+		serviceKonto.put(FIELD_TYPE, type);
+		return serviceKonto;
+	}
+
+	private void saveVorgangWithHeaderServiceKonto(Document serviceKonto) {
+		dbTestUtils.saveVorgang(new Document(Map.of(FIELD_HEADER, Map.of(FIELD_SERVICE_KONTO, serviceKonto))));
+	}
+
+	private void saveVorgangWithEingangServiceKonto(Document serviceKonto) {
+		var eingang = new Document(Map.of(FIELD_HEADER, Map.of(FIELD_SERVICE_KONTO, serviceKonto)));
+		dbTestUtils.saveVorgang(new Document(Map.of(FIELD_EINGANG, List.of(eingang))));
+	}
+
+	private Document loadHeaderServiceKonto() {
+		var vorgangs = dbTestUtils.findVorgang(new Query());
+		return getServiceKonto(vorgangs.getFirst());
+	}
+
+	private Document loadEingangServiceKonto() {
+		var vorgangs = dbTestUtils.findVorgang(new Query());
+		return getServiceKonto(vorgangs.getFirst().getList(FIELD_EINGANG, Document.class).getFirst());
+	}
+
+	private Document getServiceKonto(Document vorgang) {
+		return vorgang.get(FIELD_HEADER, Document.class).get(FIELD_SERVICE_KONTO, Document.class);
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java
index 359c21709666e3ec0f2c5c8e07d5317ba351dc79..22d8cf0cbc1376ac758021b083685c7ac518efdb 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java
@@ -37,13 +37,13 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
 import de.ozgcloud.command.Command;
+import de.ozgcloud.command.VorgangAssignedEvent;
 import de.ozgcloud.command.VorgangCreatedEvent;
 import de.ozgcloud.vorgang.command.CommandService;
 import de.ozgcloud.vorgang.command.CommandTestFactory;
 import de.ozgcloud.vorgang.status.StatusChangedEvent;
 import de.ozgcloud.vorgang.vorgang.SetAktenzeichenCompletedEvent;
 import de.ozgcloud.vorgang.vorgang.Vorgang;
-import de.ozgcloud.vorgang.vorgang.VorgangAssignedEvent;
 import de.ozgcloud.vorgang.vorgang.VorgangDeletedEvent;
 import de.ozgcloud.vorgang.vorgang.VorgangDeletedEventTestFactory;
 import de.ozgcloud.vorgang.vorgang.VorgangService;
@@ -127,7 +127,7 @@ class SearchEventListenerTest {
 	@Nested
 	class TestOnDeletedVorgang {
 
-		private VorgangDeletedEvent event = VorgangDeletedEventTestFactory.create();
+		private final VorgangDeletedEvent event = VorgangDeletedEventTestFactory.create();
 
 		@Test
 		void shouldCallService() {
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java
index 7bf1b282a7708c1e16fab1f6f6a71873b5f245bf..831f430ef392061414267c8478689cbe90f1a712 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java
@@ -1,6 +1,6 @@
 package de.ozgcloud.vorgang.registry;
 
-import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationResponse;
+import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcVorgangManagerRegistrationResponse;
 
 public class GrpcRegistrationResponseTestFactory {
 	public static GrpcVorgangManagerRegistrationResponse create() {
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java
index 7f5f58b5e47dd5ecb7cf48219f092d42fc1134ad..aaf11c29d09a7e063e209f2b97b070bd7880a303 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java
@@ -1,25 +1,24 @@
 package de.ozgcloud.vorgang.registry;
 
-import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
 
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.Spy;
-import org.springframework.test.util.ReflectionTestUtils;
+
+import de.ozgcloud.vorgang.VorgangManagerProperties;
 
 class RegistryServiceTest {
+
 	private static final String ORGANISATION_EINHEITEN_ID = "123456";
 	private static final List<String> ORGANISATION_EINHEITEN_IDS = List.of(ORGANISATION_EINHEITEN_ID);
-	private static final Optional<String> VORGANG_MANAGER_ADDRESS = Optional.of("address");
+	private static final String VORGANG_MANAGER_ADDRESS = "vorgang-manager-address";
 
 	@Spy
 	@InjectMocks
@@ -27,34 +26,24 @@ class RegistryServiceTest {
 
 	@Mock
 	private ZufiRemoteService zufiRemoteService;
+	@Mock
+	private VorgangManagerProperties vorgangManagerProperties;
 
-	@DisplayName("Test registering the VorgangManager")
-	@Nested
-	class TestRegistryVorgangManager {
-		@BeforeEach
-		void initVorgangManagerAddress() {
-			ReflectionTestUtils.setField(registryService, "vorgangManagerAddress", VORGANG_MANAGER_ADDRESS);
-		}
-
-		@Test
-		void shouldCallZuFiRemoteService() {
-			registryService.registerVorgangManager(ORGANISATION_EINHEITEN_IDS);
-
-			verify(zufiRemoteService).registerVorgangManager(anyList(), any());
-		}
+	@Test
+	void shouldCallZuFiRemoteService() {
+		when(vorgangManagerProperties.getAddress()).thenReturn(VORGANG_MANAGER_ADDRESS);
 
-		@Test
-		void shouldNotCallZuFiRemoteServiceOnEmptyOrganisationsEinheitenIds() {
-			registryService.registerVorgangManager(Collections.emptyList());
+		registryService.registerVorgangManager(ORGANISATION_EINHEITEN_IDS);
 
-			verify(zufiRemoteService, never()).registerVorgangManager(anyList(), any());
-		}
+		verify(zufiRemoteService).registerVorgangManager(ORGANISATION_EINHEITEN_IDS, VORGANG_MANAGER_ADDRESS);
+	}
 
-		@Test
-		void shouldNotCallServiceStub() {
-			registryService.registerAddress(ORGANISATION_EINHEITEN_IDS, Optional.empty());
+	@DisplayName("should not call zufi remote service when organisationseinheitenIds is empty")
+	@Test
+	void shouldNotCallRegisterAddress() {
+		registryService.registerVorgangManager(Collections.emptyList());
 
-			verify(zufiRemoteService, never()).registerVorgangManager(any(), any());
-		}
+		Mockito.verifyNoInteractions(zufiRemoteService);
 	}
+
 }
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java
index 384ca37218780385c58092d40024998380a4e4c2..a09030f20ec00b66f0edb7d1823874c5a0f41101 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java
@@ -14,8 +14,8 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 
 import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor;
-import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationRequest;
-import de.ozgcloud.zufi.grpc.registration.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub;
+import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcVorgangManagerRegistrationRequest;
+import de.ozgcloud.zufi.grpc.organisationseinheit.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub;
 
 class ZufiRemoteServiceTest {
 	private static final String ORGANISATIONS_EINHEITEN_ID = "123456";
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
index fb8085fe48a868c0c40ff629bf19ae4ec4dcea32..c6a8daf26e2d1696cad785c5cb1c66cf1d73f33a 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
@@ -47,6 +47,7 @@ import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.security.access.AccessDeniedException;
 
 import de.ozgcloud.command.Command;
+import de.ozgcloud.command.VorgangAssignedEvent;
 import de.ozgcloud.command.VorgangCreatedEvent;
 import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
 import de.ozgcloud.vorgang.command.CommandTestFactory;
diff --git a/vorgang-manager-server/src/test/resources/application-itcase.yml b/vorgang-manager-server/src/test/resources/application-itcase.yml
index 96b714f6f813bab2e43f054df6147c89749a6dbf..2ab5f3470287edaf719a5db27b0cba4480042d0b 100644
--- a/vorgang-manager-server/src/test/resources/application-itcase.yml
+++ b/vorgang-manager-server/src/test/resources/application-itcase.yml
@@ -11,7 +11,19 @@ grpc:
     port: -1
 
 ozgcloud:
+  administration:
+    sync:
+      enabled: false
+  application:
+    address: localhost
   aktenzeichen: de.ozgcloud.vorgang.vorgang.AktenzeichenProviderEA
+  notification:
+    scheduling:
+      enabled: false
 
 mongock:
   enabled: false
+spring:
+  cloud:
+    config:
+      enabled: false
diff --git a/vorgang-manager-utils/pom.xml b/vorgang-manager-utils/pom.xml
index ce3991a3ca9e937f0065db46d5ac9a5fe8367ba8..0d232ba161371a55bbf231ffac22faaab225a57d 100644
--- a/vorgang-manager-utils/pom.xml
+++ b/vorgang-manager-utils/pom.xml
@@ -37,7 +37,7 @@
 	<groupId>de.ozgcloud.vorgang</groupId>
 	<artifactId>vorgang-manager-utils</artifactId>
 	<name>OZG-Cloud Vorgang Manager Utils</name>
-	<version>2.14.1</version>
+	<version>2.15.0-SNAPSHOT</version>
 
 	<properties>
 		<maven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>