diff --git a/Jenkinsfile b/Jenkinsfile
index 23cf53a8e0ac1221c26bbe9964ccc87e5ccd836a..a143bcf648a7f2add38b2f1467d90d2b59d06b8e 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -47,7 +47,7 @@ pipeline {
                     sh 'xmlstarlet ed --pf -L -N w="http://maven.apache.org/POM/4.0.0" -u "//w:project/w:properties/w:maven.compiler.source" -v 11 vorgang-manager/vorgang-manager-interface/pom.xml'
                     sh 'xmlstarlet ed --pf -L -N w="http://maven.apache.org/POM/4.0.0" -u "//w:project/w:properties/w:maven.compiler.target" -v 11 vorgang-manager/vorgang-manager-interface/pom.xml'
 
-                    sh 'mvn -f vorgang-manager/vorgang-manager-interface -s $MAVEN_SETTINGS -Djava.version=11 install'
+                    sh 'mvn -f vorgang-manager/vorgang-manager-interface -s $MAVEN_SETTINGS --no-transfer-progress -Djava.version=11 install'
                 }
             }
         }
@@ -57,7 +57,7 @@ pipeline {
             steps {
                 configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) {
                     sh 'mvn --version'
-                    sh 'mvn -f eingang-manager/formcycle-adapter/formcycle-adapter-interface -s $MAVEN_SETTINGS -Djava.version=11 install'
+                    sh 'mvn --no-transfer-progress -f eingang-manager/formcycle-adapter/formcycle-adapter-interface -s $MAVEN_SETTINGS -Djava.version=11 install'
                 }
             }
         }
@@ -69,7 +69,7 @@ pipeline {
                 }
                 configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) {
                     sh 'mvn --version'
-                    sh 'mvn -s $MAVEN_SETTINGS -P ci-build clean install -Dmaven.wagon.http.retryHandler.count=3'
+                    sh 'mvn --no-transfer-progress -s $MAVEN_SETTINGS -P ci-build clean install -Dmaven.wagon.http.retryHandler.count=3'
                         
                     script {
 	                    if (env.BRANCH_NAME == 'master') {
@@ -110,7 +110,7 @@ pipeline {
                     FAILED_STAGE = env.STAGE_NAME
                 }
                 configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) {
-                    sh 'mvn -s $MAVEN_SETTINGS -DskipTests deploy -Dmaven.wagon.http.retryHandler.count=3'
+                    sh 'mvn --no-transfer-progress -s $MAVEN_SETTINGS -DskipTests deploy -Dmaven.wagon.http.retryHandler.count=3'
                 }
             }
         }
@@ -129,7 +129,7 @@ pipeline {
                 configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) {
 
                         sh 'mvn --version'
-                        sh 'mvn -s $MAVEN_SETTINGS -P ci-build fc-deploy:deploy -DfcDeployUrl="https://formcycle.dev.ozg-sh.de/formcycle" -DfcDeployClientId="2" -DfcDeployToken=adminhase23 -DskipTests=true -Dmaven.wagon.http.retryHandler.count=3'
+                        sh 'mvn --no-transfer-progress -s $MAVEN_SETTINGS -P ci-build fc-deploy:deploy -DfcDeployUrl="https://formcycle.dev.ozg-sh.de/formcycle" -DfcDeployClientId="2" -DfcDeployToken=adminhase23 -DskipTests=true -Dmaven.wagon.http.retryHandler.count=3'
                 }
             }
             post {
diff --git a/pom.xml b/pom.xml
index e16eb694a5b52e4f75d9a1994af0e7b9d7097b9a..9e9338347ed3d86c51fc34ef0f5c37eb2e1e83ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,15 +15,15 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
 		<!-- Version of FORMCYCLE to built against. -->
-		<xfc.version>8.1.0</xfc.version>
-		<fc-server-maven-plugin.version>8.0.3</fc-server-maven-plugin.version>
+		<xfc.version>8.1.2</xfc.version>
+		<fc-server-maven-plugin.version>8.1.0</fc-server-maven-plugin.version>
 		<fc-deploy-plugin-maven-plugin.version>8.0.1</fc-deploy-plugin-maven-plugin.version>
 
-		<formcycle-adapter-interface.version>2.6.0</formcycle-adapter-interface.version>
-		<lombok.version>1.18.30</lombok.version>
-		<junit-jupiter.version>5.10.1</junit-jupiter.version>
-		<mockito.version>5.8.0</mockito.version>
-		<assertj.version>3.25.0</assertj.version>
+		<formcycle-adapter-interface.version>2.10.0-SNAPSHOT</formcycle-adapter-interface.version>
+		<lombok.version>1.18.32</lombok.version>
+		<junit-jupiter.version>5.10.2</junit-jupiter.version>
+		<mockito.version>5.12.0</mockito.version>
+		<assertj.version>3.26.0</assertj.version>
 		<htmlcleaner.version>2.29</htmlcleaner.version>
 
 		<!-- Maven plugin versions -->
diff --git a/release-notes.md b/release-notes.md
index dd12fa2dbf5edc64c262e798775a958bef7e523f..5c4f844ea7a3c73ce81b0e6e163cdbce85e3cb6b 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -1,5 +1,8 @@
 # Version 2.5.0
 
+- Wenn im Formular Anhänge hochgeladen wurden, aber keine Dateien gefunden wurden, wird eine Warnung mit dem Fehlercode
+  MISSING_ATTACHMENTS und einer entsprechenden Nachricht protokolliert.
+
 # Version 2.4.0
 
 - Flexibles Einbetten des AKDB-Templates in die OZG Cloud Plugin. Ab diese Version kann das AKDB-Template, das zur
diff --git a/src/main/java/de/ozgcloud/formcycle/OzgPluginExecutor.java b/src/main/java/de/ozgcloud/formcycle/OzgPluginExecutor.java
index 7bb4cb98d0af20941e506dd8d25e45373c0d4ed5..a7b0ab2d1c3be9d2d10555bc2c591e0e4ee2d22d 100644
--- a/src/main/java/de/ozgcloud/formcycle/OzgPluginExecutor.java
+++ b/src/main/java/de/ozgcloud/formcycle/OzgPluginExecutor.java
@@ -22,23 +22,20 @@
  */
 package de.ozgcloud.formcycle;
 
-import static java.util.Objects.*;
-
-import java.util.EnumMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.function.Predicate;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import de.ozgcloud.eingang.formcycle.FormCycleConfirmationResponse;
 import de.ozgcloud.formcycle.attachment.AttachmentMapper;
-import de.ozgcloud.formcycle.attachment.AttachmentType;
 import de.ozgcloud.formcycle.attachment.FormcycleAttachment;
 import de.ozgcloud.formcycle.errorhandling.OzgPluginSoftError;
 import de.ozgcloud.formcycle.errorhandling.Warning;
+import de.ozgcloud.formcycle.formdata.FormData;
 import de.ozgcloud.formcycle.formdata.OzgCloudFormDataMapper;
 import de.ozgcloud.formcycle.formdata.PluginFormDataAdapter;
 import de.xima.fc.entities.Attachment;
@@ -57,36 +54,56 @@ public final class OzgPluginExecutor {
 
 	public ExecutionResult execute() {
 		LOG.debug("Executing plugin WorkflowElementNodePlugin");
-		var formData = pluginFormDataAdapter.readFormData();
-		var resultBuilder = ExecutionResult.builder();
-		formData.getWarnings().forEach(resultBuilder::warning);
-		var attachments = getAttachedFiles(formData.getAttachmentUuids());
-		if (isNull(attachments.get(AttachmentType.REPRESENTATION))) {
-			resultBuilder.warning(
-					buildWarning("Representation is missing. Ensure workflow is configured to attach form view to form data."));
-		}
+		var formData = addRepresentations(pluginFormDataAdapter.readFormData());
+		formData = addAttachments(formData);
+		return buildExecutionResult(sendFormData(formData), formData);
+	}
 
-		var formcycleFormData = ozgCloudFormDataMapper.map(formData);
-		var formCycleConfirmationResponse = ozgHttpClient.send(formcycleFormData, attachments.get(AttachmentType.ATTACHMENT),
-				attachments.get(AttachmentType.REPRESENTATION));
-		LOG.debug("Formcycle adapter response: {}", formCycleConfirmationResponse);
+	FormData addRepresentations(FormData formData) {
+		var representations = getAttachedFiles(attachmentUuid -> !formData.getAttachmentUuids().contains(attachmentUuid));
+		if (representations.isEmpty()) {
+			return formData.toBuilder().warning(buildMissingRepresentationsWarning(formData.getRequestId())).build();
+		}
+		return formData.toBuilder().representations(representations).build();
+	}
 
-		return resultBuilder.vorgangnummer(formCycleConfirmationResponse.getVorgangNummer()).build();
+	Warning buildMissingRepresentationsWarning(String requestId) {
+		return buildWarning(OzgPluginSoftError.MISSING_REPRESENTATION,
+				String.format("Representation is missing. Ensure workflow is configured to attach form view to form data. (Request ID: %s)",
+						requestId));
 	}
 
-	Map<AttachmentType, Set<FormcycleAttachment>> getAttachedFiles(Set<String> uploadFieldUuids) {
-		var resultMap = new EnumMap<AttachmentType, Set<FormcycleAttachment>>(AttachmentType.class);
-		for (Attachment attachment : attachmentsSupplier.get()) {
-			if (uploadFieldUuids.contains(attachment.getUUID())) {
-				resultMap.computeIfAbsent(AttachmentType.ATTACHMENT, e -> new HashSet<>()).add(attachmentMapper.map(attachment));
-				continue;
-			}
-			resultMap.computeIfAbsent(AttachmentType.REPRESENTATION, e -> new HashSet<>()).add(attachmentMapper.map(attachment));
+	FormData addAttachments(FormData formData) {
+		if (formData.getAttachmentUuids().isEmpty()) {
+			return formData;
+		}
+		var attachments = getAttachedFiles(formData.getAttachmentUuids()::contains);
+		if (attachments.isEmpty()) {
+			return formData.toBuilder().warning(buildMissingAttachmentsWarning(formData.getRequestId())).build();
 		}
-		return resultMap;
+		return formData.toBuilder().attachments(attachments).build();
+	}
+
+	List<FormcycleAttachment> getAttachedFiles(Predicate<String> attachmentUuidFilter) {
+		return attachmentsSupplier.get().stream().filter(attachment -> attachmentUuidFilter.test(attachment.getUUID())).map(attachmentMapper::map)
+				.collect(Collectors.toList());
+	}
+
+	Warning buildMissingAttachmentsWarning(String requestId) {
+		return buildWarning(OzgPluginSoftError.MISSING_ATTACHMENTS,
+				String.format("Attachments uploaded in the form were not included in the form data. (RequestId: %s)", requestId));
+	}
+
+	private Warning buildWarning(OzgPluginSoftError warningCode, String message) {
+		return Warning.builder().errorCode(warningCode).message(message).build();
+	}
+
+	FormCycleConfirmationResponse sendFormData(FormData formData) {
+		return ozgHttpClient.send(ozgCloudFormDataMapper.map(formData), formData.getAttachments(), formData.getRepresentations());
 	}
 
-	Warning buildWarning(String message) {
-		return Warning.builder().errorCode(OzgPluginSoftError.MISSING_REPRESENTATION).message(message).build();
+	ExecutionResult buildExecutionResult(FormCycleConfirmationResponse response, FormData formData) {
+		LOG.debug("Formcycle adapter response: {}", response);
+		return ExecutionResult.builder().vorgangnummer(response.getVorgangNummer()).warnings(formData.getWarnings()).build();
 	}
 }
diff --git a/src/main/java/de/ozgcloud/formcycle/errorhandling/OzgPluginSoftError.java b/src/main/java/de/ozgcloud/formcycle/errorhandling/OzgPluginSoftError.java
index 89a7c086735893b3a77b311504bcb0ed6b569a00..6536c2a00aa81f9c2ed1595b0aaee1a2328e93f0 100644
--- a/src/main/java/de/ozgcloud/formcycle/errorhandling/OzgPluginSoftError.java
+++ b/src/main/java/de/ozgcloud/formcycle/errorhandling/OzgPluginSoftError.java
@@ -31,9 +31,11 @@ package de.ozgcloud.formcycle.errorhandling;
  */
 public enum OzgPluginSoftError {
 
-  /** Indicates that representation of a formular was not attached to form data */
-  MISSING_REPRESENTATION,
-  /** Indicates that user connected the formular with a service konto and it supply an unexpected trust level value */
-  UNEXPECTED_TRUST_LEVEL
+	/** Indicates that representation of a formular was not attached to form data */
+	MISSING_REPRESENTATION,
+	/** Indicates that the attachments uploaded in the form were not included in the form data. */
+	MISSING_ATTACHMENTS,
+	/** Indicates that user connected the formular with a service konto and it supply an unexpected trust level value */
+	UNEXPECTED_TRUST_LEVEL
 
 }
diff --git a/src/main/java/de/ozgcloud/formcycle/formdata/FormData.java b/src/main/java/de/ozgcloud/formcycle/formdata/FormData.java
index fc31fca5bf5e1ebb4c2ffef8af3dc42509c71376..0f9b306bf5d5acf15fbc2766ece3b89f1cff9512 100644
--- a/src/main/java/de/ozgcloud/formcycle/formdata/FormData.java
+++ b/src/main/java/de/ozgcloud/formcycle/formdata/FormData.java
@@ -26,28 +26,39 @@ package de.ozgcloud.formcycle.formdata;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import java.util.UUID;
 
+import de.ozgcloud.formcycle.attachment.FormcycleAttachment;
 import de.ozgcloud.formcycle.errorhandling.Warning;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Singular;
 
 @Getter
-@Builder
+@Builder(toBuilder = true)
 public class FormData {
 
+	private final String requestId = UUID.randomUUID().toString();
 
+	private long formId;
 	private String organisationsEinheitId;
 
 	private String formName;
 
 	private ServiceKonto serviceKonto;
 
+	@Singular
 	private Set<String> attachmentNames;
+	@Singular
 	private Set<String> attachmentUuids;
 
 	private List<FormNode> fieldData;
 
+	@Singular
+	private List<FormcycleAttachment> attachments;
+	@Singular
+	private List<FormcycleAttachment> representations;
+
 	@Singular
 	private List<Warning> warnings;
 
diff --git a/src/main/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapper.java b/src/main/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapper.java
index b0a47fa1efefb0acc1872622367758d2d7b63d83..abca97a7b51db26e2569d14b944a222948de313a 100644
--- a/src/main/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapper.java
+++ b/src/main/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapper.java
@@ -123,6 +123,8 @@ public class OzgCloudFormDataMapper {
 
 	FormCycleFormHeader buildHeader(FormData formData) {
 		FormCycleFormHeader.Builder builder = FormCycleFormHeader.newBuilder()
+				.setRequestId(formData.getRequestId())
+				.setFormId(Long.toString(formData.getFormId()))
 				.setReceivedAt(ZonedDateTime.now().toString())
 				.setOrganisationsEinheitId(formData.getOrganisationsEinheitId());
 		Optional.ofNullable(formData.getFormName()).ifPresent(builder::setFormName);
diff --git a/src/main/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapter.java b/src/main/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapter.java
index 4361bf1197872d73bbf78f1934cae77585fac2d0..bbb9fbd22c6a7b9c87cc3d76d0b86a16f83d2688 100644
--- a/src/main/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapter.java
+++ b/src/main/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapter.java
@@ -68,8 +68,8 @@ public class PluginFormDataAdapter {
 
 		var formFields = buildFormData();
 		Set<String> uploadFieldNames = getUploadFieldNames();
-
 		var formDataBuilder = FormData.builder()
+				.formId(environmentData.getProject().getId())
 				.formName(getFormName())
 				.organisationsEinheitId(organisationsEinheitId)
 				.fieldData(formFields)
diff --git a/src/main/resources/WEB-INF/properties/i18n_de.properties b/src/main/resources/WEB-INF/properties/i18n_de.properties
index 951c16bbc7e9c30f1c5d26846baf169f0bec7da8..43c9385bb8867ff78cd0bb08d470119001382362 100644
--- a/src/main/resources/WEB-INF/properties/i18n_de.properties
+++ b/src/main/resources/WEB-INF/properties/i18n_de.properties
@@ -13,6 +13,7 @@ de.ozgcloud.formcycle.OzgCloudPlugin.errVal.OZGCLOUD_REQUEST_FAILED.exceptionId
 
 # Soft Errors
 de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.MISSING_REPRESENTATION          = Warnung Code, wenn Formular Representation nicht angeh�ngt werden konnte.
+de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.MISSING_ATTACHMENTS=Warnung Code, wenn im Formular hochgeladene Anh�nge nicht gefunden worden sind.
 de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.UNEXPECTED_TRUST_LEVEL          = Warnung Code, wenn das Vertrauensniveau der BayernID Verbindung einen unerwarteten Wert hat oder leer ist.
 
 OzgPluginWorkflowNodeProperties.section_settings = Einstellungen
diff --git a/src/test/java/de/ozgcloud/formcycle/OzgPluginExecutorTest.java b/src/test/java/de/ozgcloud/formcycle/OzgPluginExecutorTest.java
index 9e6a6578205823a1175bacc0675b2ee4cfd36527..6b0269def717eff88ad3b6852107350171ab72de 100644
--- a/src/test/java/de/ozgcloud/formcycle/OzgPluginExecutorTest.java
+++ b/src/test/java/de/ozgcloud/formcycle/OzgPluginExecutorTest.java
@@ -30,6 +30,8 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
+import java.util.function.Predicate;
 import java.util.function.Supplier;
 
 import org.junit.jupiter.api.BeforeEach;
@@ -45,13 +47,13 @@ import org.mockito.Spy;
 import de.ozgcloud.eingang.formcycle.FormCycleConfirmationResponse;
 import de.ozgcloud.eingang.formcycle.FormCycleFormData;
 import de.ozgcloud.formcycle.attachment.AttachmentMapper;
-import de.ozgcloud.formcycle.attachment.AttachmentType;
 import de.ozgcloud.formcycle.attachment.FormcycleAttachment;
 import de.ozgcloud.formcycle.attachment.FormcycleAttachmentTestFactory;
 import de.ozgcloud.formcycle.errorhandling.NodeThrewExceptionFactory;
 import de.ozgcloud.formcycle.errorhandling.OzgPluginSoftError;
 import de.ozgcloud.formcycle.errorhandling.Warning;
 import de.ozgcloud.formcycle.formdata.FormData;
+import de.ozgcloud.formcycle.formdata.FormDataTestFactory;
 import de.ozgcloud.formcycle.formdata.OzgCloudFormDataMapper;
 import de.ozgcloud.formcycle.formdata.PluginFormDataAdapter;
 import de.xima.fc.entities.Attachment;
@@ -59,6 +61,8 @@ import lombok.SneakyThrows;
 
 class OzgPluginExecutorTest {
 
+	private final static FormData FORM_DATA = FormDataTestFactory.create();
+
 	@Spy
 	@InjectMocks
 	private OzgPluginExecutor executor;
@@ -81,120 +85,206 @@ class OzgPluginExecutorTest {
 	@Nested
 	class TestExecution {
 
-		private static final String VORGANGS_NUMMER = "12345";
-
 		@Mock
 		private FormCycleConfirmationResponse response;
 		@Mock
-		private FormData formData;
+		private ExecutionResult executionResult;
 		@Mock
-		private Warning warning;
-
-		@Captor
-		private ArgumentCaptor<List<FormcycleAttachment>> attachmentsCapture;
+		private FormData formDataWithRepresentations;
+		@Mock
+		private FormData formDataWithAttachments;
 
 		@SneakyThrows
 		@BeforeEach
 		void setup() {
-			when(response.getVorgangNummer()).thenReturn(VORGANGS_NUMMER);
 			when(ozgHttpClient.send(any(), any(), any())).thenReturn(response);
-			when(pluginFormDataAdapter.readFormData()).thenReturn(formData);
+			when(pluginFormDataAdapter.readFormData()).thenReturn(FORM_DATA);
+			doReturn(formDataWithRepresentations).when(executor).addRepresentations(any());
+			doReturn(formDataWithAttachments).when(executor).addAttachments(any());
+			doReturn(executionResult).when(executor).buildExecutionResult(any(), any());
 		}
 
-		@Nested
-		class TestMapping {
+		@Test
+		void shouldCallPluginFormDataAdapter() {
+			executor.execute();
+
+			verify(pluginFormDataAdapter).readFormData();
+		}
 
-			@BeforeEach
-			void setup() {
-				when(attachmentSupplier.get()).thenReturn(List.of());
-			}
+		@Test
+		void shouldCallAddRepresentations() {
+			executor.execute();
 
-			@SneakyThrows
-			@Test
-			void shouldExtractAsGrpc() {
-				executor.execute();
+			verify(executor).addRepresentations(FORM_DATA);
+		}
 
-				verify(ozgCloudFormDataMapper).map(formData);
-			}
+		@Test
+		void shouldCallAddAttachments() {
+			executor.execute();
 
-			@SneakyThrows
-			@Test
-			void shouldCreateSuccessResult() {
-				var executionResult = executor.execute();
+			verify(executor).addAttachments(formDataWithRepresentations);
+		}
 
-				assertThat(executionResult.getVorgangnummer()).isEqualTo(VORGANGS_NUMMER);
-			}
+		@Test
+		void shouldCallSendFormData() {
+			executor.execute();
 
-			@Test
-			void shouldAddWarnings() {
-				when(formData.getWarnings()).thenReturn(List.of(warning));
+			verify(executor).sendFormData(formDataWithAttachments);
+		}
 
-				var executionResult = executor.execute();
+		@Test
+		void shouldCallBuildExecutionResult() {
+			executor.execute();
 
-				assertThat(executionResult.getWarnings()).contains(warning);
-			}
+			verify(executor).buildExecutionResult(response, formDataWithAttachments);
 		}
 
-		@Nested
-		@DisplayName("Send data")
-		class TestSendData {
+		@Test
+		void shouldReturnExecutionResult() {
+			var result = executor.execute();
 
-			@Mock
-			private FormCycleFormData formcycleFormData;
+			assertThat(result).isSameAs(executionResult);
+		}
+	}
 
-			@Captor
-			private ArgumentCaptor<Set<FormcycleAttachment>> attachmentsCapture;
+	@Nested
+	class TestAddRepresentations {
+
+		@Mock
+		private Warning warning;
+
+		@Captor
+		private ArgumentCaptor<Predicate<String>> filterPredicateCapture;
+
+		private final FormData formData = FormDataTestFactory.createBuilder().clearRepresentations().build();
 
-			@SneakyThrows
-			@BeforeEach
-			void setup() {
-				when(ozgCloudFormDataMapper.map(any())).thenReturn(formcycleFormData);
-			}
+		@Test
+		void shouldCallGetAttachedFiles() {
+			doReturn(List.of(FormcycleAttachmentTestFactory.create())).when(executor).getAttachedFiles(any());
 
-			@SneakyThrows
-			@Test
-			void shouldSendFormData() {
-				when(attachmentSupplier.get()).thenReturn(List.of());
+			executor.addRepresentations(formData);
+
+			verify(executor).getAttachedFiles(filterPredicateCapture.capture());
+			assertThat(filterPredicateCapture.getValue().test(FormDataTestFactory.ATTACHMENT_UUID)).isFalse();
+		}
 
-				executor.execute();
+		@Test
+		void shouldSetRepresentations() {
+			var representation = FormcycleAttachmentTestFactory.create();
+			doReturn(List.of(representation)).when(executor).getAttachedFiles(any());
+
+			var result = executor.addRepresentations(formData);
+
+			assertThat(result.getRepresentations()).hasSize(1).first().isEqualTo(representation);
+		}
+
+		@Test
+		void shouldNotAddAnyWarnings() {
+			doReturn(List.of(FormcycleAttachmentTestFactory.create())).when(executor).getAttachedFiles(any());
+
+			var result = executor.addRepresentations(FormDataTestFactory.createBuilder().clearWarnings().build());
+
+			assertThat(result.getWarnings()).isEmpty();
+		}
+
+		@Test
+		void shouldCallBuildMissingRepresentationsWarning() {
+			doReturn(Collections.emptyList()).when(executor).getAttachedFiles(any());
+			doReturn(warning).when(executor).buildMissingRepresentationsWarning(any());
+
+			executor.addRepresentations(formData);
+
+			verify(executor).buildMissingRepresentationsWarning(formData.getRequestId());
+		}
+
+		@Test
+		void shouldAddWhenMissingRepresentations() {
+			doReturn(Collections.emptyList()).when(executor).getAttachedFiles(any());
+			doReturn(warning).when(executor).buildMissingRepresentationsWarning(any());
+
+			var result = executor.addRepresentations(formData);
+
+			assertThat(result.getWarnings()).hasSize(1).first().isSameAs(warning);
+		}
+
+	}
+
+	@Nested
+	class TestAddAttachments {
+
+		@Mock
+		private Warning warning;
+
+		@Captor
+		private ArgumentCaptor<Set<String>> attachmentUuidsCapture;
+		@Captor
+		private ArgumentCaptor<Predicate<String>> filterPredicateCapture;
+
+		private FormData formData = FormDataTestFactory.createBuilder().clearAttachments().build();
+
+		@Test
+		void shouldReturnSameWhenNoAttachmentUuids() {
+			var expectedFormData = FormDataTestFactory.createBuilder().clearAttachmentUuids().build();
+
+			var result = executor.addAttachments(expectedFormData);
+
+			assertThat(result).isSameAs(expectedFormData);
+		}
+
+		@Test
+		void shouldCallGetAttachedFiles() {
+			doReturn(List.of(FormcycleAttachmentTestFactory.create())).when(executor).getAttachedFiles(any());
+
+			executor.addAttachments(formData);
+
+			verify(executor).getAttachedFiles(filterPredicateCapture.capture());
+			assertThat(filterPredicateCapture.getValue().test(FormDataTestFactory.ATTACHMENT_UUID)).isTrue();
+		}
+
+		@Test
+		void shouldSetAttachments() {
+			var representation = FormcycleAttachmentTestFactory.create();
+			doReturn(List.of(representation)).when(executor).getAttachedFiles(any());
+
+			var result = executor.addAttachments(formData);
+
+			assertThat(result.getAttachments()).hasSize(1).first().isEqualTo(representation);
+		}
+
+		@Test
+		void shouldNotAddAnyWarnings() {
+			doReturn(List.of(FormcycleAttachmentTestFactory.create())).when(executor).getAttachedFiles(any());
 
-				verify(ozgHttpClient).send(eq(formcycleFormData), any(), any());
-			}
+			var result = executor.addAttachments(FormDataTestFactory.createBuilder().clearWarnings().build());
 
-			@SneakyThrows
-			@Test
-			void shouldSendAttachments() {
-				var expectedAttachment = FormcycleAttachmentTestFactory.create();
-				doReturn(Map.of(
-						AttachmentType.ATTACHMENT, Set.of(expectedAttachment),
-						AttachmentType.REPRESENTATION, Set.of(FormcycleAttachmentTestFactory.create()))).when(executor).getAttachedFiles(any());
+			assertThat(result.getWarnings()).isEmpty();
+		}
 
-				executor.execute();
+		@Test
+		void shouldCallBuildMissingAttachmentsWarning() {
+			doReturn(Collections.emptyList()).when(executor).getAttachedFiles(any());
+			doReturn(warning).when(executor).buildMissingAttachmentsWarning(any());
 
-				verify(ozgHttpClient).send(any(), attachmentsCapture.capture(), any());
-				assertThat(attachmentsCapture.getValue()).containsExactlyInAnyOrder(expectedAttachment);
-			}
+			executor.addAttachments(formData);
 
-			@SneakyThrows
-			@Test
-			void shouldSendRepresentations() {
-				var expectedRepresentations = FormcycleAttachmentTestFactory.create();
-				doReturn(Map.of(
-						AttachmentType.ATTACHMENT, Set.of(FormcycleAttachmentTestFactory.create()),
-						AttachmentType.REPRESENTATION, Set.of(expectedRepresentations))).when(executor).getAttachedFiles(any());
+			verify(executor).buildMissingAttachmentsWarning(formData.getRequestId());
+		}
 
-				executor.execute();
+		@Test
+		void shouldAddWhenMissingAttachments() {
+			doReturn(Collections.emptyList()).when(executor).getAttachedFiles(any());
+			doReturn(warning).when(executor).buildMissingAttachmentsWarning(any());
 
-				verify(ozgHttpClient).send(any(), any(), attachmentsCapture.capture());
-				assertThat(attachmentsCapture.getValue()).containsExactlyInAnyOrder(expectedRepresentations);
-			}
+			var result = executor.addAttachments(formData);
 
+			assertThat(result.getWarnings()).hasSize(1).first().isSameAs(warning);
 		}
+
 	}
 
 	@Nested
 	@DisplayName("Attachment's handling")
-	class TestGetAttachments {
+	class TestGetAttachedFiles {
 
 		@Mock
 		private Attachment attachment;
@@ -205,44 +295,32 @@ class OzgPluginExecutorTest {
 		void shouldReturnEmpty() {
 			when(attachmentSupplier.get()).thenReturn(Collections.emptyList());
 
-			var attachedFiles = getAttachedFiles(Collections.emptySet());
+			var attachedFiles = executor.getAttachedFiles(uuid -> true);
 
 			assertThat(attachedFiles).isEmpty();
 		}
 
 		@Test
-		void shouldGetAttachments() {
-			var expectedAttachment = initAttachment(attachment);
-
-			var attachedFiles = getAttachedFiles(Set.of(FormcycleAttachmentTestFactory.UUID));
-
-			assertThat(attachedFiles).hasSize(1).containsOnly(Map.entry(AttachmentType.ATTACHMENT, Set.of(expectedAttachment)));
-		}
-
-		@Test
-		void shouldGetRepresentations() {
-			var expectedAttachment = initAttachment(representation);
+		void shouldCallMapper() {
+			initAttachment();
 
-			var attachedFiles = getAttachedFiles(Set.of(FormcycleAttachmentTestFactory.UUID));
+			executor.getAttachedFiles(uuid -> true);
 
-			assertThat(attachedFiles).hasSize(1).containsOnly(Map.entry(AttachmentType.ATTACHMENT, Set.of(expectedAttachment)));
+			verify(attachmentMapper).map(attachment);
 		}
 
 		@Test
-		@DisplayName("should return all attachments as representations when no upload fields")
-		@SneakyThrows
-		void shouldGetAllRepresentations() {
-			when(attachmentMapper.map(any())).thenAnswer(invocation -> mock(FormcycleAttachment.class));
-			when(attachmentSupplier.get()).thenReturn(List.of(attachment, representation));
+		void shouldApplyFilterAndReturnAttachments() {
+			var expectedAttachment = initAttachment();
+			when(representation.getUUID()).thenReturn(UUID.randomUUID().toString());
+			when(attachmentSupplier.get()).thenReturn(List.of(representation, attachment));
 
-			var attachedFiles = getAttachedFiles(Collections.emptySet());
+			var attachedFiles = executor.getAttachedFiles(FormcycleAttachmentTestFactory.UUID::equals);
 
-			assertThat(attachedFiles).hasSize(1);
-			assertThat(attachedFiles.get(AttachmentType.REPRESENTATION)).hasSize(2);
+			assertThat(attachedFiles).hasSize(1).containsExactly(expectedAttachment);
 		}
 
-		@SneakyThrows
-		private FormcycleAttachment initAttachment(Attachment attachment) {
+		private FormcycleAttachment initAttachment() {
 			var expectedAttachment = FormcycleAttachmentTestFactory.create();
 			when(attachmentMapper.map(any())).thenReturn(expectedAttachment);
 			when(attachment.getUUID()).thenReturn(FormcycleAttachmentTestFactory.UUID);
@@ -250,29 +328,128 @@ class OzgPluginExecutorTest {
 			return expectedAttachment;
 		}
 
-		@SneakyThrows
-		private Map<AttachmentType, Set<FormcycleAttachment>> getAttachedFiles(Set<String> ids) {
-			return executor.getAttachedFiles(ids);
+	}
+
+	@Nested
+	class TestBuildMissingRepresentationsWarning {
+
+		private final String REQUEST_ID = "REQUEST_ID";
+
+		@Test
+		void shouldSetErrorCode() {
+			var warning = executor.buildMissingRepresentationsWarning(REQUEST_ID);
+
+			assertThat(warning.getErrorCode()).isEqualTo(OzgPluginSoftError.MISSING_REPRESENTATION.name());
+		}
+
+		@Test
+		void shouldSetMessage() {
+			var warning = executor.buildMissingRepresentationsWarning(REQUEST_ID);
+
+			assertThat(warning.getMessage()).contains(REQUEST_ID);
 		}
 	}
 
 	@Nested
-	class TestBuildWarning {
+	class TestBuildMissingAttachmentsWarning {
 
-		private final String MESSAGE = "message";
+		private final String REQUEST_ID = "REQUEST_ID";
 
 		@Test
 		void shouldSetErrorCode() {
-			var warning = executor.buildWarning(MESSAGE);
+			var warning = executor.buildMissingAttachmentsWarning(REQUEST_ID);
 
-			assertThat(warning.getErrorCode()).isEqualTo(OzgPluginSoftError.MISSING_REPRESENTATION.toString());
+			assertThat(warning.getErrorCode()).isEqualTo(OzgPluginSoftError.MISSING_ATTACHMENTS.name());
 		}
 
 		@Test
 		void shouldSetMessage() {
-			var warning = executor.buildWarning(MESSAGE);
+			var warning = executor.buildMissingAttachmentsWarning(REQUEST_ID);
+
+			assertThat(warning.getMessage()).contains(REQUEST_ID);
+		}
+	}
+
+	@Nested
+	@DisplayName("Send data")
+	class TestSendData {
+
+		@Mock
+		private FormCycleFormData formcycleFormData;
+		@Mock
+		private FormCycleConfirmationResponse response;
+
+		@Captor
+		private ArgumentCaptor<List<FormcycleAttachment>> attachmentsCapture;
+		@Captor
+		private ArgumentCaptor<List<FormcycleAttachment>> representationsCapture;
+
+		@Test
+		void shouldCallMapper() {
+			sendFormData();
+
+			verify(ozgCloudFormDataMapper).map(FORM_DATA);
+		}
+
+		@Test
+		void shouldSendFormData() {
+			when(ozgCloudFormDataMapper.map(any())).thenReturn(formcycleFormData);
+
+			sendFormData();
+
+			verify(ozgHttpClient).send(eq(formcycleFormData), any(), any());
+		}
+
+		@Test
+		void shouldSendAttachments() {
+			sendFormData();
+
+			verify(ozgHttpClient).send(any(), attachmentsCapture.capture(), any());
+			assertThat(attachmentsCapture.getValue()).hasSize(1).first().extracting("uuid").isEqualTo(FormDataTestFactory.ATTACHMENT_UUID);
+		}
+
+		@Test
+		void shouldSendRepresentations() {
+			sendFormData();
+
+			verify(ozgHttpClient).send(any(), any(), representationsCapture.capture());
+			assertThat(representationsCapture.getValue()).hasSize(1).first().extracting("uuid").isEqualTo(FormDataTestFactory.REPRESENTATION_UUID);
+		}
+
+		@Test
+		void shouldReturnResponse() {
+			when(ozgHttpClient.send(any(), any(), any())).thenReturn(response);
+
+			var result = sendFormData();
+
+			assertThat(result).isSameAs(response);
+		}
+
+		private FormCycleConfirmationResponse sendFormData() {
+			return executor.sendFormData(FORM_DATA);
+		}
+	}
+
+	@Nested
+	class TestBuildExecutionResults {
+
+		@Mock
+		private Warning warning;
+
+		@Test
+		void shouldSetVorgangNummer() {
+			var result = executor.buildExecutionResult(FormCycleConfirmationResponseTestFactory.create(), FORM_DATA);
+
+			assertThat(result.getVorgangnummer()).isEqualTo(FormCycleConfirmationResponseTestFactory.VORGANG_NUMMER);
+		}
+
+		@Test
+		void shouldSetWarnings() {
+			var formData = FormDataTestFactory.createBuilder().clearWarnings().warning(warning).build();
+
+			var result = executor.buildExecutionResult(FormCycleConfirmationResponseTestFactory.create(), formData);
 
-			assertThat(warning.getMessage()).isEqualTo(MESSAGE);
+			assertThat(result.getWarnings()).containsExactly(warning);
 		}
 	}
 }
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/formcycle/attachment/FormcycleAttachmentTestFactory.java b/src/test/java/de/ozgcloud/formcycle/attachment/FormcycleAttachmentTestFactory.java
index 7dbb6461e0503ac7598d1079bc118a214ac2bfdc..3fd7153ba0fd509691145e94ceb31da1a3e4dca2 100644
--- a/src/test/java/de/ozgcloud/formcycle/attachment/FormcycleAttachmentTestFactory.java
+++ b/src/test/java/de/ozgcloud/formcycle/attachment/FormcycleAttachmentTestFactory.java
@@ -19,7 +19,7 @@ public class FormcycleAttachmentTestFactory {
 		return createBuilder().build();
 	}
 
-	static FormcycleAttachmentBuilder createBuilder() {
+	public static FormcycleAttachmentBuilder createBuilder() {
 		return FormcycleAttachment.builder()
 				.uuid(UUID)
 				.fileName(FILE_NAME)
diff --git a/src/test/java/de/ozgcloud/formcycle/formdata/FormDataTestFactory.java b/src/test/java/de/ozgcloud/formcycle/formdata/FormDataTestFactory.java
index dba1ab267371b28e71824c28aa6050a2a648cc6b..7054470000ee7b948993df84531800953f35ab65 100644
--- a/src/test/java/de/ozgcloud/formcycle/formdata/FormDataTestFactory.java
+++ b/src/test/java/de/ozgcloud/formcycle/formdata/FormDataTestFactory.java
@@ -24,12 +24,19 @@ package de.ozgcloud.formcycle.formdata;
 
 import java.util.List;
 import java.util.Set;
+import java.util.UUID;
+
+import de.ozgcloud.formcycle.attachment.FormcycleAttachmentTestFactory;
 
 public class FormDataTestFactory {
 
+	public static final long FORM_ID = 1;
+	public static final String FORM_ID_STR = String.valueOf(FORM_ID);
 	public static final String FORM_NAME = "formular";
 	public static final String ORGANISATIONS_EINHEIT_ID = "12345";
 	public static final String ATTACHMENT_ID = "file.pdf";
+	public static final String ATTACHMENT_UUID = UUID.randomUUID().toString();
+	public static final String REPRESENTATION_UUID = UUID.randomUUID().toString();
 	public static final String FIELD_VALUE_1 = "on";
 	public static final List<FormNode> FIELD_DATA = List.of(FormNodeTestFactory.create());
 
@@ -39,10 +46,14 @@ public class FormDataTestFactory {
 
 	public static FormData.FormDataBuilder createBuilder() {
 		return FormData.builder()
+				.formId(FORM_ID)
 				.formName(FORM_NAME)
 				.organisationsEinheitId(ORGANISATIONS_EINHEIT_ID)
 				.fieldData(FIELD_DATA)
 				.attachmentNames(Set.of(ATTACHMENT_ID))
+				.attachmentUuids(Set.of(ATTACHMENT_UUID))
+				.representation(FormcycleAttachmentTestFactory.createBuilder().uuid(REPRESENTATION_UUID).build())
+				.attachment(FormcycleAttachmentTestFactory.createBuilder().uuid(ATTACHMENT_UUID).build())
 				.serviceKonto(ServiceKontoTestFactory.create());
 	}
 }
diff --git a/src/test/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapperTest.java b/src/test/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapperTest.java
index 82cbc184f4b32628d8aa357a2d4e9e3f0d7e43aa..b3b2eb22f14480efedd4786146e9d273379d1ac3 100644
--- a/src/test/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapperTest.java
+++ b/src/test/java/de/ozgcloud/formcycle/formdata/OzgCloudFormDataMapperTest.java
@@ -165,7 +165,7 @@ class OzgCloudFormDataMapperTest {
 
 				var formFields = mapper.mapFormFields(formNode);
 
-				assertThat(formFields).first().extracting(GrpcFormField::getLabel).toString().isEmpty();
+				assertThat(formFields).first().extracting(GrpcFormField::getLabel, STRING).isEmpty();
 			}
 
 			@Test
@@ -174,7 +174,7 @@ class OzgCloudFormDataMapperTest {
 
 				var formFields = mapper.mapFormFields(formNode);
 
-				assertThat(formFields).first().extracting(GrpcFormField::getName).toString().isEmpty();
+				assertThat(formFields).first().extracting(GrpcFormField::getName, STRING).isEmpty();
 			}
 		}
 
@@ -245,7 +245,6 @@ class OzgCloudFormDataMapperTest {
 
 			@Test
 			void shouldSetLabel() {
-
 				var subform = mapper.mapSubForm(formNode).get();
 
 				assertThat(subform.getLabel()).isEqualTo(StructureMockFactory.ITEM_TITLE);
@@ -355,31 +354,45 @@ class OzgCloudFormDataMapperTest {
 	}
 
 	@Nested
-	@DisplayName("Map header")
-	class TestHeader {
+	@DisplayName("build header")
+	class TestBuildHeader {
 
 		private final FormData formData = FormDataTestFactory.create();
 
 		@Test
 		void shouldSetReceivedTime() {
-			var ozgFormDataHeader = mapper.map(formData).getHeader();
+			var ozgFormDataHeader = mapper.buildHeader(formData);
 
 			assertThat(ozgFormDataHeader.getReceivedAt()).isNotNull();
 		}
 
+		@Test
+		void shouldSetFormId() {
+			var ozgFormDataHeader = mapper.buildHeader(formData);
+
+			assertThat(ozgFormDataHeader.getFormId()).isEqualTo(FORM_ID_STR);
+		}
+
 		@Test
 		void shouldSetFormName() {
-			var ozgFormDataHeader = mapper.map(formData).getHeader();
+			var ozgFormDataHeader = mapper.buildHeader(formData);
 
 			assertThat(ozgFormDataHeader.getFormName()).isEqualTo(FormDataTestFactory.FORM_NAME);
 		}
 
 		@Test
 		void shouldSetOrganisationsEinheitId() {
-			var ozgFormDataHeader = mapper.map(formData).getHeader();
+			var ozgFormDataHeader = mapper.buildHeader(formData);
 
 			assertThat(ozgFormDataHeader.getOrganisationsEinheitId()).isEqualTo(ORGANISATIONS_EINHEIT_ID);
 		}
+
+		@Test
+		void shouldSetRequestId() {
+			var ozgFormDataHeader = mapper.buildHeader(formData);
+
+			assertThat(ozgFormDataHeader.getRequestId()).isEqualTo(formData.getRequestId());
+		}
 	}
 
 	@Nested
diff --git a/src/test/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapterTest.java b/src/test/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapterTest.java
index 8343e162c9a81ff569938cb207c0e02cd4242cba..0b4535319967d1f0114e093bbd6339854d878573 100644
--- a/src/test/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapterTest.java
+++ b/src/test/java/de/ozgcloud/formcycle/formdata/PluginFormDataAdapterTest.java
@@ -81,6 +81,9 @@ class PluginFormDataAdapterTest {
 		private static final String UPLOAD_FIELD_NAME = "upload";
 		private final String ATTACHMENT_UUID = UUID.randomUUID().toString();
 
+		@Mock
+		private Projekt project;
+
 		private FormNode formNode = FormNodeTestFactory.create();
 
 		@BeforeEach
@@ -92,6 +95,8 @@ class PluginFormDataAdapterTest {
 			doReturn(Set.of(FormDataTestFactory.ATTACHMENT_ID)).when(adapter).getAttachmentNames(any());
 			doReturn(Set.of(ATTACHMENT_UUID)).when(adapter).getAttachmentUuids(any());
 			doNothing().when(adapter).addServiceKonto(any());
+			when(project.getId()).thenReturn(FormDataTestFactory.FORM_ID);
+			when(environmentData.getProject()).thenReturn(project);
 		}
 
 		@Test
@@ -108,6 +113,13 @@ class PluginFormDataAdapterTest {
 			verify(adapter).getUploadFieldNames();
 		}
 
+		@Test
+		void shouldSetFormId() {
+			var result = adapter.readFormData();
+
+			assertThat(result.getFormId()).isEqualTo(FormDataTestFactory.FORM_ID);
+		}
+
 		@Test
 		void shouldSetFormName() {
 			var result = adapter.readFormData();
@@ -358,15 +370,6 @@ class PluginFormDataAdapterTest {
 		@Mock
 		private FormFieldMetaData formFieldMetaData;
 
-		private Map<String, Map<String, String>> valueOptionsMap = Map.of(PluginDataTestFactory.FIELD_VALUE,
-				Map.of(PluginFormDataAdapter.TEXT_KEY, PluginDataTestFactory.TEXT_MAP_VALUE));
-
-		@BeforeEach
-		void setup() {
-			//			when(formFieldMetaData.getType()).thenReturn(EFormFieldTyp.SELECT);
-			//			when(formDataAdapter.getFieldMetaData(anyString(), anyBoolean())).thenReturn(formFieldMetaData);
-		}
-
 		@DisplayName("should return input when")
 		@ParameterizedTest(name = "value = \"{0}\"")
 		@NullAndEmptySource