diff --git a/lombok.config b/lombok.config
index a06fa130e8af26b659f2d3a0cb1114cd966a9b0e..f881e23c3720b1ad363aac0f5c1fe615a66a5d90 100644
--- a/lombok.config
+++ b/lombok.config
@@ -28,4 +28,5 @@ lombok.log.log4j.flagUsage = ERROR
 lombok.data.flagUsage = ERROR
 lombok.nonNull.exceptionType = IllegalArgumentException
 lombok.addLombokGeneratedAnnotation = true
-lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
\ No newline at end of file
+lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
+lombok.copyableAnnotations += net.devh.boot.grpc.client.inject.GrpcClient
\ No newline at end of file
diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
index 4b9faa2ee2b6334bb92d024bcbc0f248abd0ad0b..a5932236210a96e8b671969620f939ad14619ca6 100644
--- a/src/main/helm/templates/deployment.yaml
+++ b/src/main/helm/templates/deployment.yaml
@@ -163,6 +163,12 @@ spec:
           - name: grpc_client_zufi-manager_negotiationType
             value: {{ (.Values.zufiManager).grpcClientNegotiationType | default "PLAINTEXT" }}
           {{- end}}
+          {{- if (.Values.forwarding).enabled }}
+          - name: grpc_client_forwarder_address
+            value: {{ (.Values.forwarding).address }}
+          - name: grpc_client_forwarder_negotiationType
+            value: {{ (.Values.forwarding).grpcClientNegotiationType | default "TLS" }}
+          {{- end }}
           {{- if not (.Values.database).useExternal }}
           - name: spring_data_mongodb_uri
             valueFrom:
diff --git a/src/main/helm/templates/network_policy.yaml b/src/main/helm/templates/network_policy.yaml
index b8750949572c54207885c21dc488aca7fb0b7b58..4e6fb3e0ac202c3f763aa5a23e040a5c53767f9c 100644
--- a/src/main/helm/templates/network_policy.yaml
+++ b/src/main/helm/templates/network_policy.yaml
@@ -22,7 +22,7 @@
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
 #
 
-{{- if not (.Values.networkPolicy).disabled }} 
+{{- if not (.Values.networkPolicy).disabled }}
 apiVersion: networking.k8s.io/v1
 kind: NetworkPolicy
 metadata:
@@ -39,10 +39,10 @@ spec:
   - ports:
     - port: 9090
     from:
-    - podSelector: 
+    - podSelector:
         matchLabels:
           component: alfa
-    - podSelector: 
+    - podSelector:
         matchLabels:
           ozg-component: eingangsadapter
     - podSelector:
@@ -50,7 +50,7 @@ spec:
           ozg-component: xta-adapter
 {{- if ((.Values.ozgcloud).aggregationManager).enabled }}
   - from:
-    - podSelector: 
+    - podSelector:
         matchLabels:
           component: aggregation-manager
     ports:
@@ -69,7 +69,7 @@ spec:
     - namespaceSelector:
         matchLabels:
           kubernetes.io/metadata.name: {{((.Values.ozgcloud).antragraum).antragraumProxyNamespace | default "antragraum-proxy"}}
-      podSelector: 
+      podSelector:
         matchLabels:
           component: antragraum-proxy
 {{- end }}
@@ -87,7 +87,7 @@ spec:
               - xta-adapter
     ports:
     - protocol: TCP
-      port: 9090 
+      port: 9090
 
 {{- with (.Values.networkPolicy).additionalIngressConfigLocal }}
 {{ toYaml . | indent 2 }}
@@ -114,7 +114,7 @@ spec:
       - port: 27017
         protocol: TCP
   - to:
-    - podSelector: 
+    - podSelector:
         matchLabels:
           component: user-manager
     ports:
@@ -122,7 +122,7 @@ spec:
         protocol: TCP
 {{- if ((.Values.ozgcloud).bayernid).enabled }}
   - to:
-    - podSelector: 
+    - podSelector:
         matchLabels:
           component: bayernid-proxy
       namespaceSelector:
@@ -130,14 +130,14 @@ spec:
           kubernetes.io/metadata.name: {{ required "ozgcloud.bayernid.proxy.namespace must be set if bayernid is enabled" (((.Values.ozgcloud).bayernid).proxy).namespace }}
     ports:
       - port: 9090
-        protocol: TCP 
+        protocol: TCP
 {{- end }}
 {{- if ((.Values.ozgcloud).antragraum).enabled }}
   - to:
       - namespaceSelector:
           matchLabels:
             kubernetes.io/metadata.name: {{((.Values.ozgcloud).infoManager).namespace | default "info-manager"}}
-        podSelector: 
+        podSelector:
           matchLabels:
             component: info-manager
 {{- end }}
@@ -146,13 +146,25 @@ spec:
     - namespaceSelector:
         matchLabels:
           kubernetes.io/metadata.name: {{ required "zufiManager.namespace must be set if zufiManager server is enabled" (.Values.zufiManager).namespace }}
-      podSelector: 
+      podSelector:
         matchLabels:
           component: zufi-server
     ports:
       - port: 9090
         protocol: TCP
 {{- end }}
+{{- if (.Values.forwarding).enabled }}
+  - to:
+    - namespaceSelector:
+        matchLabels:
+          kubernetes.io/metadata.name: {{ required "forwarding.namespace must be set if forwarding is enabled" (.Values.forwarding).namespace }}
+      podSelector:
+        matchLabels:
+          component: {{ required "forwarding.serviceName must be set if forwarding is enabled" (.Values.forwarding).serviceName }}
+    ports:
+      - port: 9090
+        protocol: TCP
+{{- end }}
 {{- if ((.Values.ozgcloud).muk).enabled }}
   - to:
     - podSelector:
diff --git a/src/test/helm/deployment_forwarder_env_test.yaml b/src/test/helm/deployment_forwarder_env_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fd7a77f810286abfaef04c28e5aa0c6f35abbc0c
--- /dev/null
+++ b/src/test/helm/deployment_forwarder_env_test.yaml
@@ -0,0 +1,81 @@
+#
+# 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: test forwarder environment
+release:
+  name: vorgang-manager
+  namespace: by-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  baseUrl: test.sh.ozg-cloud.de
+  ozgcloud:
+    environment: dev
+    bezeichner: helm
+  imagePullSecret: test-image-pull-secret
+tests:
+  - it: should be disabled by default
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_forwarder_address
+          any: true
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_forwarder_negotiationType
+          any: true
+  - it: should set the grpc forwarder client address
+    set:
+      forwarding:
+        enabled: true
+        address: https://forwarder.my-wonderful-domain.local:9000
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_forwarder_address
+            value: https://forwarder.my-wonderful-domain.local:9000
+  - it: should set the default negotiation type
+    set:
+      forwarding:
+        enabled: true
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_forwarder_negotiationType
+            value: TLS
+  - it: should set the negotiation type
+    set:
+      forwarding:
+        enabled: true
+        grpcClientNegotiationType: PLAINTEXT
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_forwarder_negotiationType
+            value: PLAINTEXT
\ No newline at end of file
diff --git a/src/test/helm/network_policy_test.yaml b/src/test/helm/network_policy_test.yaml
index 17c7a47611643bec68e2d54f90ccfbc74b4954be..fff3066c0175266c277e88c895455d1548f13f89 100644
--- a/src/test/helm/network_policy_test.yaml
+++ b/src/test/helm/network_policy_test.yaml
@@ -30,7 +30,7 @@ templates:
 
 tests:
   - it: should match apiVersion
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
@@ -38,7 +38,7 @@ tests:
           of: networking.k8s.io/v1
 
   - it: should match kind
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
@@ -46,7 +46,7 @@ tests:
           of: NetworkPolicy
 
   - it: validate metadata
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
@@ -57,7 +57,7 @@ tests:
             namespace: by-helm-test
 
   - it: should set policy target matchLabel
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
@@ -67,9 +67,8 @@ tests:
             matchLabels:
               component: vorgang-manager
 
-
   - it: should add policyType Egress
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
@@ -78,7 +77,7 @@ tests:
           content: Egress
 
   - it: should add policyType Ingress
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
@@ -87,44 +86,44 @@ tests:
           content: Ingress
 
   - it: should add ingress rule for eingangsmanager and alfa
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
       - contains:
           path: spec.ingress
           content:
-              ports:
+            ports:
               - port: 9090
-              from:
-              - podSelector: 
+            from:
+              - podSelector:
                   matchLabels:
                     component: alfa
-              - podSelector: 
+              - podSelector:
                   matchLabels:
                     ozg-component: eingangsadapter
               - podSelector:
-                      matchLabels:
-                        ozg-component: xta-adapter
+                  matchLabels:
+                    ozg-component: xta-adapter
 
   - it: should add ingress rule for monitoring scraper
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
       - contains:
           path: spec.ingress
           content:
-              ports:
+            ports:
               - port: 8081
                 protocol: TCP
-              from:
-              - namespaceSelector: 
+            from:
+              - namespaceSelector:
                   matchLabels:
                     name: openshift-user-workload-monitoring
 
   - it: should set monitoring namespace for monitoring scraper ingress rule
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
         monitoringNamespace: test-monitoring
@@ -132,11 +131,11 @@ tests:
       - contains:
           path: spec.ingress
           content:
-              ports:
+            ports:
               - port: 8081
                 protocol: TCP
-              from:
-              - namespaceSelector: 
+            from:
+              - namespaceSelector:
                   matchLabels:
                     name: test-monitoring
 
@@ -148,16 +147,16 @@ tests:
         antragraum:
           enabled: true
     asserts:
-    - contains:
-        path: spec.ingress
-        content:
-          from:
-            - namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: antragraum-proxy
-              podSelector: 
-                matchLabels:
-                  component: antragraum-proxy
+      - contains:
+          path: spec.ingress
+          content:
+            from:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: antragraum-proxy
+                podSelector:
+                  matchLabels:
+                    component: antragraum-proxy
 
   - it: should set ingress rule for antragraum-proxy if antragraum is enabled
     set:
@@ -168,17 +167,16 @@ tests:
           enabled: true
           antragraumProxyNamespace: antragraum-proxy
     asserts:
-    - contains:
-        path: spec.ingress
-        content:
-          from:
-            - namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: antragraum-proxy
-              podSelector: 
-                matchLabels:
-                  component: antragraum-proxy
-
+      - contains:
+          path: spec.ingress
+          content:
+            from:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: antragraum-proxy
+                podSelector:
+                  matchLabels:
+                    component: antragraum-proxy
 
   - it: should not add ingress rule for antragraum if antragraum is disabled
     set:
@@ -188,16 +186,16 @@ tests:
         antragraum:
           enabled: false
     asserts:
-    - notContains:
-        path: spec.ingress
-        content:
-          from:
-            - namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: antragraum
-              podSelector: 
-                matchLabels:
-                  component: antragraum-server
+      - notContains:
+          path: spec.ingress
+          content:
+            from:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: antragraum
+                podSelector:
+                  matchLabels:
+                    component: antragraum-server
 
   - it: should not add ingress rule for antragraum-proxy if antragraum is disabled
     set:
@@ -207,40 +205,40 @@ tests:
         antragraum:
           enabled: false
     asserts:
-    - notContains:
-        path: spec.ingress
-        content:
-          from:
-            - namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: antragraum-proxy
-              podSelector: 
-                matchLabels:
-                  component: antragraum-proxy
-        any: true
+      - notContains:
+          path: spec.ingress
+          content:
+            from:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: antragraum-proxy
+                podSelector:
+                  matchLabels:
+                    component: antragraum-proxy
+          any: true
 
   - it: should add default ingress rule for zentraler-eingang
     set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
-    - contains:
-        path: spec.ingress
-        content:
-          from:
-          - namespaceSelector:
-              matchLabels:
-                kubernetes.io/metadata.name: zentraler-eingang
-            podSelector:
-              matchExpressions:
-                - key: ozg-component
-                  operator: In
-                  values:
-                    - eingangsadapter
-                    - xta-adapter
-          ports:
-          - protocol: TCP
-            port: 9090 
+      - contains:
+          path: spec.ingress
+          content:
+            from:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: zentraler-eingang
+                podSelector:
+                  matchExpressions:
+                    - key: ozg-component
+                      operator: In
+                      values:
+                        - eingangsadapter
+                        - xta-adapter
+            ports:
+              - protocol: TCP
+                port: 9090
 
   - it: should add ingress rule for zentraler-eingang
     set:
@@ -248,24 +246,23 @@ tests:
         dnsServerNamespace: test-dns-namespace
         zentralerEingangNamespace: custom-namespace
     asserts:
-    - contains:
-        path: spec.ingress
-        content:
-          from:
-          - namespaceSelector:
-              matchLabels:
-                kubernetes.io/metadata.name: custom-namespace
-            podSelector:
-              matchExpressions:
-                - key: ozg-component
-                  operator: In
-                  values:
-                    - eingangsadapter
-                    - xta-adapter
-          ports:
-          - protocol: TCP
-            port: 9090 
-
+      - contains:
+          path: spec.ingress
+          content:
+            from:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: custom-namespace
+                podSelector:
+                  matchExpressions:
+                    - key: ozg-component
+                      operator: In
+                      values:
+                        - eingangsadapter
+                        - xta-adapter
+            ports:
+              - protocol: TCP
+                port: 9090
 
   - it: should add egress rule to elasticsearch
     set:
@@ -275,16 +272,16 @@ tests:
       - contains:
           path: spec.egress
           content:
-              to:
+            to:
               - namespaceSelector:
                   matchLabels:
                     kubernetes.io/metadata.name: elastic-system
                 podSelector:
                   matchLabels:
-                    elasticsearch.k8s.elastic.co/cluster-name : ozg-search-cluster
-              ports:
-                - port: 9200
-                  protocol: TCP
+                    elasticsearch.k8s.elastic.co/cluster-name: ozg-search-cluster
+            ports:
+              - port: 9200
+                protocol: TCP
 
   - it: should add egress rule to mongodb
     set:
@@ -294,13 +291,13 @@ tests:
       - contains:
           path: spec.egress
           content:
-              to:
+            to:
               - podSelector:
                   matchLabels:
                     component: ozgcloud-mongodb
-              ports:
-                - port: 27017
-                  protocol: TCP
+            ports:
+              - port: 27017
+                protocol: TCP
 
   - it: should add egress rule to user-manager
     set:
@@ -310,13 +307,13 @@ tests:
       - contains:
           path: spec.egress
           content:
-              to:
-              - podSelector: 
+            to:
+              - podSelector:
                   matchLabels:
                     component: user-manager
-              ports:
-                - port: 9000
-                  protocol: TCP
+            ports:
+              - port: 9000
+                protocol: TCP
 
   - it: should add egress rule to nachrichten-bayernid-proxy if bayernid is enabled
     set:
@@ -332,15 +329,15 @@ tests:
           path: spec.egress
           content:
             to:
-            - podSelector: 
-                matchLabels:
-                  component: bayernid-proxy
-              namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: bayernidProxyNamespace
+              - podSelector:
+                  matchLabels:
+                    component: bayernid-proxy
+                namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: bayernidProxyNamespace
             ports:
-            - port: 9090
-              protocol: TCP 
+              - port: 9090
+                protocol: TCP
 
   - it: should not add egress rule to bayernid-proxy if bayernid is disabled
     set:
@@ -354,16 +351,16 @@ tests:
           path: spec.egress
           content:
             to:
-            - podSelector: 
-                matchLabels:
-                  component: bayernid-proxy
-              namespaceSelector:
-                matchLabels:
-                      kubernetes.io/metadata.name: bayernidProxyNamespace
+              - podSelector:
+                  matchLabels:
+                    component: bayernid-proxy
+                namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: bayernidProxyNamespace
             ports:
-            - port: 9090
-              protocol: TCP 
-  
+              - port: 9090
+                protocol: TCP
+
   - it: should throw error if bayernid-proxy is enabled but bayernid namespace is not set
     set:
       networkPolicy:
@@ -390,7 +387,7 @@ tests:
               - namespaceSelector:
                   matchLabels:
                     kubernetes.io/metadata.name: info-manager
-                podSelector: 
+                podSelector:
                   matchLabels:
                     component: info-manager
 
@@ -411,7 +408,7 @@ tests:
               - namespaceSelector:
                   matchLabels:
                     kubernetes.io/metadata.name: info-manager2
-                podSelector: 
+                podSelector:
                   matchLabels:
                     component: info-manager
 
@@ -430,7 +427,7 @@ tests:
               - namespaceSelector:
                   matchLabels:
                     kubernetes.io/metadata.name: info-manager
-                podSelector: 
+                podSelector:
                   matchLabels:
                     component: info-manager
 
@@ -446,16 +443,15 @@ tests:
           path: spec.egress
           content:
             to:
-            - podSelector: 
-                matchLabels:
-                  component: zufi-server
-              namespaceSelector:
-                matchLabels:
-                      kubernetes.io/metadata.name: zufi
+              - podSelector:
+                  matchLabels:
+                    component: zufi-server
+                namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: zufi
             ports:
-            - port: 9090
-              protocol: TCP         
-                  
+              - port: 9090
+                protocol: TCP
 
   - it: should not add egress rule to zufi server if zufi is disabled
     set:
@@ -469,14 +465,58 @@ tests:
           path: spec.egress
           content:
             to:
-            - namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: zufi
-              podSelector: 
-                matchLabels:
-                  component: zufi-server
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: zufi
+                podSelector:
+                  matchLabels:
+                    component: zufi-server
+          any: true
+
+  - it: should add egress rule to forwarding service if forwarding is enabled
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+      forwarding:
+        enabled: true
+        namespace: zentraler-eingang
+        serviceName: fs-adapter
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+            to:
+              - podSelector:
+                  matchLabels:
+                    component: fs-adapter
+                namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: zentraler-eingang
+            ports:
+              - port: 9090
+                protocol: TCP
+
+  - it: should not add egress rule to forwarding service if forwarding is disabled
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+      forwarding:
+        enabled: false
+        namespace: zentraler-eingang
+        serviceName: fs-adapter
+    asserts:
+      - notContains:
+          path: spec.egress
+          content:
+            to:
+              - podSelector:
+                  matchLabels:
+                    component: fs-adapter
+                namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: zentraler-eingang
           any: true
-  
+
   - it: should throw error if zufi is enabled but zufi namespace is not set
     set:
       networkPolicy:
@@ -496,17 +536,16 @@ tests:
     asserts:
       - notContains:
           path: spec.egress
-          content: 
+          content:
             to:
-            - namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: zufi
-              podSelector: 
-                matchLabels:
-                  component: zufi-server
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: zufi
+                podSelector:
+                  matchLabels:
+                    component: zufi-server
           any: true
 
-
   - it: should add egress rule to dns service
     set:
       networkPolicy:
@@ -515,19 +554,19 @@ tests:
       - contains:
           path: spec.egress
           content:
-              to:
+            to:
               - namespaceSelector:
                   matchLabels:
                     kubernetes.io/metadata.name: test-dns-namespace
-              ports:
-                - port: 53
-                  protocol: UDP
-                - port: 53
-                  protocol: TCP
-                - port: 5353
-                  protocol: UDP
-                - port: 5353
-                  protocol: TCP
+            ports:
+              - port: 53
+                protocol: UDP
+              - port: 53
+                protocol: TCP
+              - port: 5353
+                protocol: UDP
+              - port: 5353
+                protocol: TCP
 
   - it: add ingress rule local by values
     set:
@@ -535,89 +574,89 @@ tests:
         dnsServerNamespace: test-dns-namespace
         ssoPublicIp: 51.89.117.53/32
         additionalIngressConfigGlobal:
-        - from:
-          - podSelector: 
-              matchLabels:
-                component: client2
+          - from:
+              - podSelector:
+                  matchLabels:
+                    component: client2
     asserts:
       - contains:
           path: spec.ingress
           content:
             from:
-            - podSelector: 
-                matchLabels:
-                  component: client2
+              - podSelector:
+                  matchLabels:
+                    component: client2
   - it: add ingress rule global by values
     set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
         ssoPublicIp: 51.89.117.53/32
         additionalIngressConfigLocal:
-        - from:
-          - podSelector: 
-              matchLabels:
-                component: client2
+          - from:
+              - podSelector:
+                  matchLabels:
+                    component: client2
     asserts:
       - contains:
           path: spec.ingress
           content:
             from:
-            - podSelector: 
-                matchLabels:
-                  component: client2
+              - podSelector:
+                  matchLabels:
+                    component: client2
 
   - it: add egress rules local by values
     set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
         additionalEgressConfigGlobal:
-        - to:
-          - ipBlock:
-              cidr: 1.2.3.4/32
-        - to:
-          - podSelector:
-              matchLabels:
-                component: ozg-testservice
-          ports:
-            - port: 12345
-              protocol: TCP
-    asserts:
-    - contains:
-        path: spec.egress
-        content:
-          to:
-          - ipBlock:
-              cidr: 1.2.3.4/32
-    - contains:
-        path: spec.egress
-        content:
-          to:
-          - podSelector:
-              matchLabels:
-                component: ozg-testservice
-          ports:
-            - port: 12345
-              protocol: TCP
+          - to:
+              - ipBlock:
+                  cidr: 1.2.3.4/32
+          - to:
+              - podSelector:
+                  matchLabels:
+                    component: ozg-testservice
+            ports:
+              - port: 12345
+                protocol: TCP
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+            to:
+              - ipBlock:
+                  cidr: 1.2.3.4/32
+      - contains:
+          path: spec.egress
+          content:
+            to:
+              - podSelector:
+                  matchLabels:
+                    component: ozg-testservice
+            ports:
+              - port: 12345
+                protocol: TCP
   - it: add egress rules global by values
     set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
         additionalEgressConfigLocal:
-        - to:
-          - ipBlock:
-              cidr: 1.2.3.4/32
-        - to:
-          - podSelector:
-              matchLabels:
-                additionalEgressConfigLocal: yes
-    asserts:
-    - contains:
-        path: spec.egress
-        content:
-          to:
-          - podSelector:
-              matchLabels:
-                additionalEgressConfigLocal: yes
+          - to:
+              - ipBlock:
+                  cidr: 1.2.3.4/32
+          - to:
+              - podSelector:
+                  matchLabels:
+                    additionalEgressConfigLocal: yes
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+            to:
+              - podSelector:
+                  matchLabels:
+                    additionalEgressConfigLocal: yes
 
   - it: test network policy disabled
     set:
@@ -676,15 +715,15 @@ tests:
           path: spec.egress
           content:
             to:
-            - podSelector: 
-                matchLabels:
-                  app.kubernetes.io/name: elster-transfer
-              namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: elster-transfer
+              - podSelector:
+                  matchLabels:
+                    app.kubernetes.io/name: elster-transfer
+                namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: elster-transfer
             ports:
-            - port: 8081
-              protocol: TCP
+              - port: 8081
+                protocol: TCP
 
   - it: should set elster transfer name
     set:
@@ -701,15 +740,15 @@ tests:
           path: spec.egress
           content:
             to:
-            - podSelector: 
-                matchLabels:
-                  app.kubernetes.io/name: elster-transfer-test
-              namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: elster-transfer
+              - podSelector:
+                  matchLabels:
+                    app.kubernetes.io/name: elster-transfer-test
+                namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: elster-transfer
             ports:
-            - port: 8081
-              protocol: TCP
+              - port: 8081
+                protocol: TCP
 
   - it: should not add egress rule for elster-transfer if muk is disabled
     set:
@@ -725,15 +764,15 @@ tests:
           path: spec.egress
           content:
             to:
-            - podSelector: 
-                matchLabels:
-                  app.kubernetes.io/name: elster-transfer
-              namespaceSelector:
-                matchLabels:
-                  kubernetes.io/metadata.name: elster-transfer
+              - podSelector:
+                  matchLabels:
+                    app.kubernetes.io/name: elster-transfer
+                namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: elster-transfer
           any: true
   - it: should add ingress rule for aggregation-manager
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
       ozgcloud:
@@ -743,26 +782,26 @@ tests:
       - contains:
           path: spec.ingress
           content:
-              ports:
+            ports:
               - port: 9090
                 protocol: TCP
-              from:
-              - podSelector: 
+            from:
+              - podSelector:
                   matchLabels:
                     component: aggregation-manager
 
   - it: should not add ingress rule for aggregation-manager
-    set: 
+    set:
       networkPolicy:
         dnsServerNamespace: test-dns-namespace
     asserts:
       - notContains:
           path: spec.ingress
           content:
-              ports:
+            ports:
               - port: 9090
                 protocol: TCP
-              from:
-              - podSelector: 
+            from:
+              - podSelector:
                   matchLabels:
                     component: aggregation-manager
diff --git a/vorgang-manager-server/pom.xml b/vorgang-manager-server/pom.xml
index d265423e02a345b4608f2ede9fda8f9978aa95e0..a21b718ba3809dccf567d3bd9559f0abf7bd745e 100644
--- a/vorgang-manager-server/pom.xml
+++ b/vorgang-manager-server/pom.xml
@@ -32,7 +32,7 @@
 	<parent>
 		<groupId>de.ozgcloud.common</groupId>
 		<artifactId>ozgcloud-common-parent</artifactId>
-		<version>4.11.0</version>
+		<version>4.12.0-OZG-7573-GrpcUpload-utils-SNAPSHOT</version>
 		<relativePath />
 	</parent>
 
@@ -51,7 +51,7 @@
 		<spring-boot.build-image.imageName>docker.ozg-sh.de/vorgang-manager:build-latest</spring-boot.build-image.imageName>
 
 		<zufi-manager-interface.version>1.6.0</zufi-manager-interface.version>
-
+		<common-lib.version>4.12.0-SNAPSHOT</common-lib.version>
 		<user-manager-interface.version>2.12.0</user-manager-interface.version>
 		<processor-manager.version>0.5.0</processor-manager.version>
 		<nachrichten-manager.version>2.19.0-SNAPSHOT</nachrichten-manager.version>
@@ -60,6 +60,7 @@
 		<collaboration-manager.version>0.7.0</collaboration-manager.version>
 		<archive-manager.version>0.3.0</archive-manager.version>
 		<document-manager.version>1.2.0</document-manager.version>
+		<eingang-manager-interface.version>2.19.0-SNAPSHOT</eingang-manager-interface.version>
 
 		<zip.version>2.11.5</zip.version>
 		<jsoup.version>1.15.3</jsoup.version>
@@ -81,6 +82,11 @@
 			<version>${project.version}</version>
 		</dependency>
 
+		<dependency>
+			<groupId>de.ozgcloud.common</groupId>
+			<artifactId>ozgcloud-common-lib</artifactId>
+			<version>${common-lib.version}</version>
+		</dependency>
 		<dependency>
 			<groupId>de.ozgcloud.nachrichten</groupId>
 			<artifactId>nachrichten-manager-server</artifactId>
@@ -171,6 +177,11 @@
 			<artifactId>api-lib-core</artifactId>
 			<version>${api-lib.version}</version>
 		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.eingang</groupId>
+			<artifactId>eingang-manager-interface</artifactId>
+			<version>${eingang-manager-interface.version}</version>
+		</dependency>
 
 		<!-- Spring -->
 		<dependency>
@@ -396,7 +407,8 @@
 						<env>
 							<BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"> </BPE_DELIM_JAVA_TOOL_OPTIONS>
 							<BPE_APPEND_JAVA_TOOL_OPTIONS>-Dfile.encoding=UTF-8</BPE_APPEND_JAVA_TOOL_OPTIONS>
-							<BPE_APPEND_JAVA_TOOL_OPTIONS>-Dio.grpc.netty.shaded.io.netty.maxDirectMemory=0</BPE_APPEND_JAVA_TOOL_OPTIONS>
+							<BPE_APPEND_JAVA_TOOL_OPTIONS>
+								-Dio.grpc.netty.shaded.io.netty.maxDirectMemory=0</BPE_APPEND_JAVA_TOOL_OPTIONS>
 							<BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:MaxDirectMemorySize=512m</BPE_APPEND_JAVA_TOOL_OPTIONS>
 							<BPE_APPEND_LC_ALL>en_US.UTF-8</BPE_APPEND_LC_ALL>
 						</env>
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangMapper.java
index f072e0ec6d69a38eba82bad30737494c3c465095..0c5dcaafc4d2791f2855df3ee0611a9c7707f0da 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangMapper.java
@@ -36,7 +36,7 @@ import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper;
 		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
 		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, //
 		collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
-interface EingangMapper {
+public interface EingangMapper {
 
 	@Mapping(source = "attachmentsList", target = "attachments")
 	@Mapping(source = "representationsList", target = "representations")
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapper.java
index aefc6d34ed1a5bc24bb6e1c2e3f48062b61da4e1..1170b27d77f0e96d07a6c91447a5e971dbf4de3f 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapper.java
@@ -24,9 +24,12 @@
 package de.ozgcloud.vorgang.vorgang;
 
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
 
 import com.google.protobuf.ByteString;
 
+import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile;
+import de.ozgcloud.eingang.forwarding.GrpcRepresentationFile;
 import de.ozgcloud.vorgang.files.FileIdMapper;
 
 @Mapper(uses = FileIdMapper.class)
@@ -37,4 +40,29 @@ public interface IncomingFileMapper {
 	default byte[] map(ByteString value) {
 		return value.toByteArray();
 	}
+
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "contentTypeBytes", ignore = true)
+	@Mapping(target = "fileNameBytes", ignore = true)
+	@Mapping(target = "groupNameBytes", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "vendorIdBytes", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	@Mapping(target = "fileName", source = "file.name")
+	GrpcAttachmentFile toAttachmentFile(String groupName, IncomingFile file);
+
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "contentTypeBytes", ignore = true)
+	@Mapping(target = "fileNameBytes", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "vendorIdBytes", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	@Mapping(target = "fileName", source = "name")
+	GrpcRepresentationFile toRepresentationFile(IncomingFile file);
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..63323fb8ecb106b710574deed664efbc70c3be1f
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteService.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import org.springframework.stereotype.Service;
+
+import com.google.protobuf.ByteString;
+
+import de.ozgcloud.common.binaryfile.GrpcFileUploadUtils;
+import de.ozgcloud.common.binaryfile.GrpcFileUploadUtils.FileSender;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.eingang.forwarder.RouteForwardingServiceGrpc;
+import de.ozgcloud.eingang.forwarding.GrpcAttachment;
+import de.ozgcloud.eingang.forwarding.GrpcFileContent;
+import de.ozgcloud.eingang.forwarding.GrpcRepresentation;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse;
+import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.vorgang.Eingang;
+import de.ozgcloud.vorgang.vorgang.IncomingFile;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroup;
+import de.ozgcloud.vorgang.vorgang.IncomingFileMapper;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import io.grpc.stub.CallStreamObserver;
+import io.grpc.stub.StreamObserver;
+import lombok.RequiredArgsConstructor;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Service
+@RequiredArgsConstructor
+class ForwardingRemoteService {
+
+	private static final int TIMEOUT_MINUTES = 2;
+	private final VorgangService vorgangService;
+	private final ForwardingRequestMapper forwardingRequestMapper;
+	@GrpcClient("forwarder")
+	private final RouteForwardingServiceGrpc.RouteForwardingServiceStub serviceStub;
+	private final FileService fileService;
+	private final IncomingFileMapper incomingFileMapper;
+
+	public void forward(ForwardingRequest request) {
+		CompletableFuture<Void> responseFuture = new CompletableFuture<>();
+		routeForwarding(request, new ForwardingResponseObserver(responseFuture));
+		waitForCompletion(responseFuture);
+	}
+
+	void routeForwarding(ForwardingRequest request, ForwardingResponseObserver responseObserver) {
+		var requestStreamObserver = serviceStub.withInterceptors(new VorgangManagerClientCallContextAttachingInterceptor())
+				.routeForwarding(responseObserver);
+		try {
+			sendEingang(request, requestStreamObserver);
+			requestStreamObserver.onCompleted();
+		} catch (Exception e) {
+			requestStreamObserver.onError(e);
+			throw e;
+		}
+	}
+
+	void sendEingang(ForwardingRequest request, StreamObserver<GrpcRouteForwardingRequest> requestStreamObserver) {
+		var eingang = vorgangService.getById(request.getVorgangId()).getEingangs().getFirst();
+		requestStreamObserver.onNext(buildRouteForwardingRequest(request, eingang));
+		sendAttachments(eingang.getAttachments(), requestStreamObserver);
+		sendRepresentations(eingang.getRepresentations(), requestStreamObserver);
+	}
+
+	GrpcRouteForwardingRequest buildRouteForwardingRequest(ForwardingRequest request, Eingang eingang) {
+		var routeForwarding = forwardingRequestMapper.toGrpcRouteForwarding(request, eingang);
+		return GrpcRouteForwardingRequest.newBuilder().setRouteForwarding(routeForwarding).build();
+	}
+
+	void sendAttachments(List<IncomingFileGroup> attachments, StreamObserver<GrpcRouteForwardingRequest> requestStreamObserver) {
+		for (var attachment : attachments) {
+			var groupName = attachment.getName();
+			attachment.getFiles().forEach(file -> sendAttachmentFile(requestStreamObserver, groupName, file));
+		}
+	}
+
+	private void sendAttachmentFile(StreamObserver<GrpcRouteForwardingRequest> requestStreamObserver, String groupName, IncomingFile file) {
+		var fileContentStream = fileService.getUploadedFileStream(file.getId());
+		createAttachmentFileSender(requestStreamObserver, groupName, file, fileContentStream).send();
+	}
+
+	FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> createAttachmentFileSender(
+			StreamObserver<GrpcRouteForwardingRequest> requestStreamObserver, String groupName, IncomingFile file, InputStream fileContentStream) {
+		return createSenderWithoutMetadata(this::buildAttachmentChunk, requestStreamObserver, fileContentStream)
+				.withMetaData(buildGrpcAttachmentFile(groupName, file));
+	}
+
+	GrpcRouteForwardingRequest buildAttachmentChunk(byte[] chunk, int length) {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setAttachment(GrpcAttachment.newBuilder()
+						.setContent(buildGrpcFileContent(chunk, length))
+						.build())
+				.build();
+	}
+
+	GrpcRouteForwardingRequest buildGrpcAttachmentFile(String name, IncomingFile file) {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setAttachment(GrpcAttachment.newBuilder()
+						.setFile(incomingFileMapper.toAttachmentFile(name, file))
+						.build())
+				.build();
+	}
+
+	void sendRepresentations(List<IncomingFile> representations, StreamObserver<GrpcRouteForwardingRequest> requestObserver) {
+		representations.forEach(representation -> {
+			var fileContentStream = fileService.getUploadedFileStream(representation.getId());
+			createRepresentationFileSender(requestObserver, representation, fileContentStream).send();
+		});
+	}
+
+	FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> createRepresentationFileSender(
+			StreamObserver<GrpcRouteForwardingRequest> requestStreamObserver, IncomingFile file, InputStream fileContentStream) {
+		return createSenderWithoutMetadata(this::buildRepresentationChunk, requestStreamObserver, fileContentStream)
+				.withMetaData(buildGrpcRepresentationFile(file));
+	}
+
+	FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> createSenderWithoutMetadata(
+			BiFunction<byte[], Integer, GrpcRouteForwardingRequest> chunkBuilder,
+			StreamObserver<GrpcRouteForwardingRequest> requestStreamObserver, InputStream fileContentStream) {
+		return GrpcFileUploadUtils
+				.createSender(chunkBuilder, fileContentStream, requestCallStreamObserverProvider(requestStreamObserver), false);
+	}
+
+	private Function<StreamObserver<GrpcRouteForwardingResponse>, CallStreamObserver<GrpcRouteForwardingRequest>> requestCallStreamObserverProvider(
+			StreamObserver<GrpcRouteForwardingRequest> requestStreamObserver) {
+		return response -> (CallStreamObserver<GrpcRouteForwardingRequest>) requestStreamObserver;
+	}
+
+	GrpcRouteForwardingRequest buildRepresentationChunk(byte[] chunk, int length) {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setRepresentation(GrpcRepresentation.newBuilder()
+						.setContent(buildGrpcFileContent(chunk, length))
+						.build())
+				.build();
+	}
+
+	GrpcFileContent buildGrpcFileContent(byte[] chunk, int length) {
+		var fileContentBuilder = GrpcFileContent.newBuilder();
+		if (length <= 0) {
+			fileContentBuilder.setIsEndOfFile(true);
+		} else {
+			fileContentBuilder.setContent(ByteString.copyFrom(chunk));
+		}
+		return fileContentBuilder.build();
+	}
+
+	GrpcRouteForwardingRequest buildGrpcRepresentationFile(IncomingFile file) {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setRepresentation(GrpcRepresentation.newBuilder()
+						.setFile(incomingFileMapper.toRepresentationFile(file))
+						.build())
+				.build();
+	}
+
+	void waitForCompletion(CompletableFuture<Void> responseFuture) {
+		try {
+			responseFuture.get(TIMEOUT_MINUTES, TimeUnit.MINUTES);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+			throw new TechnicalException("Waiting for finishing file upload was interrupted.", e);
+		} catch (ExecutionException e) {
+			throw new TechnicalException("Error on uploading file content.", e);
+		} catch (TimeoutException e) {
+			throw new TechnicalException("Timeout on uploading file content.", e);
+		}
+	}
+
+	@RequiredArgsConstructor
+	static class ForwardingResponseObserver implements StreamObserver<GrpcRouteForwardingResponse> {
+		private final CompletableFuture<Void> future;
+
+		@Override
+		public void onNext(GrpcRouteForwardingResponse value) {
+			// noop
+		}
+
+		@Override
+		public void onError(Throwable t) {
+			future.completeExceptionally(t);
+		}
+
+		@Override
+		public void onCompleted() {
+			future.complete(null);
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRequestMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRequestMapper.java
index e47ae180e85e18dc7466278b994f02f1886ce28b..2e32110106d1b8b4a0a39e6fd3506768152fbf95 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRequestMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRequestMapper.java
@@ -26,12 +26,24 @@ package de.ozgcloud.vorgang.vorgang.redirect;
 import java.util.Map;
 
 import org.apache.commons.collections4.MapUtils;
+import org.mapstruct.CollectionMappingStrategy;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
+import org.mapstruct.NullValueCheckStrategy;
+import org.mapstruct.NullValuePropertyMappingStrategy;
 
 import de.ozgcloud.command.Command;
+import de.ozgcloud.eingang.forwarding.GrpcEingangStub;
+import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding;
+import de.ozgcloud.vorgang.vorgang.Eingang;
+import de.ozgcloud.vorgang.vorgang.EingangMapper;
+import de.ozgcloud.vorgang.vorgang.GrpcEingang;
 
-@Mapper(imports = MapUtils.class)
+@Mapper(imports = MapUtils.class, uses = EingangMapper.class, //
+		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
+		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, //
+		collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
 interface ForwardingRequestMapper {
 
 	interface CommandBodyFields {
@@ -42,7 +54,7 @@ interface ForwardingRequestMapper {
 		String PLZ = "plz";
 		String ORT = "ort";
 	}
-	
+
 	@Mapping(target = "version", source = "relationVersion")
 	@Mapping(target = "organisationEinheit", source = "bodyObject")
 	ForwardingRequest fromCommand(Command command);
@@ -57,4 +69,17 @@ interface ForwardingRequestMapper {
 	@Mapping(target = "zipCode", expression = "java(MapUtils.getString(body, CommandBodyFields.PLZ))")
 	@Mapping(target = "city", expression = "java(MapUtils.getString(body, CommandBodyFields.ORT))")
 	Address toAddress(Map<String, Object> body);
+
+	@Mapping(target = "routeCriteria", source = "request")
+	@Mapping(target = "eingangStub", source = "eingang")
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	GrpcRouteForwarding toGrpcRouteForwarding(ForwardingRequest request, Eingang eingang);
+
+	@Mapping(target = "organisationEinheitId", source = "organisationEinheit.id")
+	GrpcRouteCriteria toGrpcRouteCriteria(ForwardingRequest request);
+
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	GrpcEingangStub toGrpcEingangStub(GrpcEingang eingang);
 }
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java
index ed26c9e9850a1361531b70b36699b5ca92c08596..6af4a3cd03f5a786e9951d30683af55e3fd53962 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java
@@ -35,7 +35,6 @@ import java.util.stream.Stream;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
@@ -56,10 +55,12 @@ import freemarker.template.Configuration;
 import freemarker.template.Template;
 import freemarker.template.TemplateException;
 import jakarta.mail.util.ByteArrayDataSource;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Service
 @Log4j2
+@RequiredArgsConstructor
 public class ForwardingService {
 
 	static final String MAIL_TEMPLATE = "/mail/redirect.txt.ftlh";
@@ -87,26 +88,15 @@ public class ForwardingService {
 	static final String SUBJECT_BESTAETIGUNG_TEMPL = "Ihr Antrag auf %s - Az: %s";
 	static final String ZIP_FILENAME_TMPL = "%s.zip";
 
-	@Autowired
-	private ForwardingRepository repository;
-
-	@Autowired
-	private Configuration freemarkerCfg;
-	@Autowired
-	private ZipBuilderService zipService;
-
-	@Autowired
-	private MailService emailService;
-
-	@Autowired
-	private VorgangService vorgangService;
-
+	private final ForwardingRepository repository;
+	private final Configuration freemarkerCfg;
+	private final ZipBuilderService zipService;
+	private final MailService emailService;
+	private final VorgangService vorgangService;
 	// TODO abhängigkeit entfernen
-	@Autowired
-	private StatusService statusService;
-
-	@Autowired
-	private ApplicationEventPublisher publisher;
+	private final StatusService statusService;
+	private final ForwardingRemoteService forwardingRemoteService;
+	private final ApplicationEventPublisher publisher;
 
 	@Value("${ozgcloud.redirect.mail-from}")
 	private String mailFrom;
@@ -332,5 +322,6 @@ public class ForwardingService {
 
 	public void forward(ForwardingRequest request) {
 		statusService.setStatusToWeitergeleitet(request.getVorgangId(), request.getVersion());
+		forwardingRemoteService.forward(request);
 	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/resources/application-local.yml b/vorgang-manager-server/src/main/resources/application-local.yml
index 6dc2ce987e221a66e9c5f7e74a23b8a82fe86557..d320959ed403f3d876855a97c6cfe3f13fddb37d 100644
--- a/vorgang-manager-server/src/main/resources/application-local.yml
+++ b/vorgang-manager-server/src/main/resources/application-local.yml
@@ -38,6 +38,10 @@ grpc:
       negotiationType: PLAINTEXT
     vorgang-manager:
       negotiationType: PLAINTEXT
+    forwarder:
+      address: static://127.0.0.1:9292
+      negotiationType: PLAINTEXT
+
   server:
     security:
       enabled: false
diff --git a/vorgang-manager-server/src/main/resources/application.yml b/vorgang-manager-server/src/main/resources/application.yml
index 7bf48c56cfe7b1d089dd2dc367d1b6bcdd25d09c..db37a3d59597564120aae7e596c1202b417bc44e 100644
--- a/vorgang-manager-server/src/main/resources/application.yml
+++ b/vorgang-manager-server/src/main/resources/application.yml
@@ -44,6 +44,8 @@ grpc:
       negotiationType: PLAINTEXT
     zufi-manager:
       negotiationType: TLS
+    forwarder:
+      negotiationType: TLS
 
   server:
     security:
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangTestFactory.java
index 9fa8813dda465272e1279e1015337fe1c15efd45..458d34b190863132535d415c903e16c999591684 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangTestFactory.java
@@ -49,6 +49,9 @@ public class EingangTestFactory {
 	public static final Map<String, Object> SUBFORM_FLAT = Map.of(SUBFORM_FIELD_NAME, SUBFORM_FIELD);
 	public static final Map<String, Object> FORM_DATA = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD, SUBFORM_NAME, SUBFORM);
 
+	public static final IncomingFileGroup ATTACHMENT = IncomingFileGroupTestFactory.create();
+	public static final IncomingFile REPRESENTATION = IncomingFileTestFactory.create();
+
 	public static Eingang create() {
 		return createBuilder().build();
 	}
@@ -59,8 +62,8 @@ public class EingangTestFactory {
 				.header(EingangHeaderTestFactory.create())
 				.antragsteller(AntragstellerTestFactory.create())
 				.formData(FORM_DATA)
-				.attachment(IncomingFileGroupTestFactory.create())
-				.representation(IncomingFileTestFactory.create())
+				.attachment(ATTACHMENT)
+				.representation(REPRESENTATION)
 				.zustaendigeStelle(ZustaendigeStelleTestFactory.create());
 	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangTestFactory.java
index 79acc665d6b1e91a113c120c9c4f3b4455499b6b..e149cbf5b3a682ae4628b2862a8d34c25fb6dd6f 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangTestFactory.java
@@ -25,12 +25,11 @@ package de.ozgcloud.vorgang.vorgang;
 
 import java.util.UUID;
 
-import de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory;
+import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory;
 
 public class GrpcEingangTestFactory {
 
 	public static final String ID = UUID.randomUUID().toString();
-	public static final GrpcSubForm SUB_FORM = GrpcSubFormTestFactory.create();
 
 	public static GrpcEingang create() {
 		return createBuilder().build();
@@ -42,7 +41,7 @@ public class GrpcEingangTestFactory {
 				.setHeader(GrpcEingangHeaderTestFactory.create())
 				.setAntragsteller(GrpcAntragstellerTestFactory.create())
 				.setZustaendigeStelle(GrpcZustaendigeStelleTestFactory.create())
-				.setFormData(GrpcFormData.newBuilder().addForm(GrpcSubFormTestFactory.create()).build())
+				.setFormData(GrpcFormDataTestFactory.create())
 				.addAttachments(GrpcIncomingFileGroupTestFactory.create())
 				.setNumberOfAttachments(4)
 				.addRepresentations(GrpcIncomingFileTestFactory.create())
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapperTest.java
index e59250ca0f7f5a57efec908af88708184b7f1d6e..771c11f67fc9cc2e3e3116bf7e208acc05a4bc49 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapperTest.java
@@ -32,6 +32,8 @@ import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
 import de.ozgcloud.vorgang.files.FileIdMapper;
+import de.ozgcloud.vorgang.vorgang.redirect.GrpcAttachmentFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.redirect.GrpcRepresentationFileTestFactory;
 
 class IncomingFileMapperTest {
 
@@ -50,4 +52,26 @@ class IncomingFileMapperTest {
 			assertThat(result).isNotNull().usingRecursiveComparison().isEqualTo(IncomingFileTestFactory.create());
 		}
 	}
+
+	@Nested
+	class TestToAttachmentFile {
+
+		@Test
+		void shouldMapToGrpcAttachmentFile() {
+			var result = mapper.toAttachmentFile(GrpcAttachmentFileTestFactory.GROUP_NAME, IncomingFileTestFactory.create());
+
+			assertThat(result).isEqualTo(GrpcAttachmentFileTestFactory.create());
+		}
+	}
+
+	@Nested
+	class TestToRepresentationFile {
+
+		@Test
+		void shouldMapToGrpcRepresentationFile() {
+			var result = mapper.toRepresentationFile(IncomingFileTestFactory.create());
+
+			assertThat(result).isEqualTo(GrpcRepresentationFileTestFactory.create());
+		}
+	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangGrpcServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangGrpcServiceITCase.java
index 24d8152f703322dd571094e5b4eefd73463fbc87..dbb11b274b6b7413244b976d5e6b23838ab8533a 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangGrpcServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangGrpcServiceITCase.java
@@ -223,7 +223,7 @@ class VorgangGrpcServiceITCase {
 		}
 
 		private static GrpcFormData expectedFormData() {
-			var grpcFormData = GrpcFormDataTestFactory.createBuilder().clearField().addAllField(formFields);
+			var grpcFormData = GrpcFormDataTestFactory.createBuilder().clearField().addAllField(formFields).clearForm();
 			for (String subFormName : List.of(TITLE_SUBFORM_1, TITLE_SUBFORM_2, TITLE_SUBFORM_3)) {
 				grpcFormData.addForm(GrpcSubForm.newBuilder()
 						.setTitle(subFormName)
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e6e63b58402a779cb7716609f773772e50b2342
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRemoteServiceTest.java
@@ -0,0 +1,796 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import org.apache.commons.lang3.RandomUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Spy;
+
+import de.ozgcloud.common.binaryfile.GrpcFileUploadUtils;
+import de.ozgcloud.common.binaryfile.GrpcFileUploadUtils.FileSender;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.common.test.ReflectionTestUtils;
+import de.ozgcloud.eingang.forwarder.RouteForwardingServiceGrpc;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingResponse;
+import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.vorgang.Eingang;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFile;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroup;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroupTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileMapper;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.redirect.ForwardingRemoteService.ForwardingResponseObserver;
+import io.grpc.stub.CallStreamObserver;
+import io.grpc.stub.StreamObserver;
+import lombok.SneakyThrows;
+
+class ForwardingRemoteServiceTest {
+
+	@Spy
+	@InjectMocks
+	private ForwardingRemoteService service;
+	@Mock
+	private VorgangService vorgangService;
+	@Mock
+	private ForwardingRequestMapper forwardingRequestMapper;
+	@Mock
+	private RouteForwardingServiceGrpc.RouteForwardingServiceStub serviceStub;
+	@Mock
+	private FileService fileService;
+	@Mock
+	private IncomingFileMapper incomingFileMapper;
+
+	@Mock
+	private StreamObserver<GrpcRouteForwardingRequest> requestObserver;
+	private final ForwardingRequest request = ForwardingRequestTestFactory.create();
+	private final Eingang eingang = EingangTestFactory.create();
+	private final Vorgang vorgang = VorgangTestFactory.createBuilder().clearEingangs().eingang(eingang).build();
+
+	@Nested
+	class TestForward {
+
+		@Captor
+		private ArgumentCaptor<ForwardingResponseObserver> responseObserverCaptor;
+		@Captor
+		private ArgumentCaptor<CompletableFuture<Void>> futureCaptor;
+
+		@BeforeEach
+		void init() {
+			doNothing().when(service).routeForwarding(any(), any());
+			doNothing().when(service).waitForCompletion(any());
+		}
+
+		@Test
+		void shouldRouteForwarding() {
+			forward();
+
+			verify(service).routeForwarding(eq(request), any(ForwardingResponseObserver.class));
+		}
+
+		@Test
+		void shouldWaitForCompletion() {
+			forward();
+
+			verify(service).waitForCompletion(futureCaptor.capture());
+			verify(service).routeForwarding(any(), responseObserverCaptor.capture());
+			assertThat(futureCaptor.getValue())
+					.isSameAs(ReflectionTestUtils.getField(responseObserverCaptor.getValue(), "future", CompletableFuture.class));
+		}
+
+		private void forward() {
+			service.forward(request);
+		}
+	}
+
+	@Nested
+	class TestRouteForwarding {
+
+		@Mock
+		private ForwardingResponseObserver responseObserver;
+
+		@BeforeEach
+		void init() {
+			when(serviceStub.withInterceptors(any())).thenReturn(serviceStub);
+		}
+
+		@Test
+		void shouldAttachClientCallContextToServiceStub() {
+			givenGrpcCallCompletedSuccessfully();
+			doNothing().when(service).sendEingang(any(), any());
+
+			routeForwarding();
+
+			verify(serviceStub).withInterceptors(any(VorgangManagerClientCallContextAttachingInterceptor.class));
+		}
+
+		@Test
+		void shouldMakeGrpcCallToRouteForwarding() {
+			givenGrpcCallCompletedSuccessfully();
+			doNothing().when(service).sendEingang(any(), any());
+
+			routeForwarding();
+
+			verify(serviceStub).routeForwarding(responseObserver);
+		}
+
+		@Nested
+		class OnSuccess {
+
+			@BeforeEach
+			void init() {
+				givenGrpcCallCompletedSuccessfully();
+				doNothing().when(service).sendEingang(any(), any());
+			}
+
+			@Test
+			void shouldSendEingang() {
+				routeForwarding();
+
+				verify(service).sendEingang(request, requestObserver);
+			}
+
+			@Test
+			void shouldCallOnCompleted() {
+				routeForwarding();
+
+				verify(requestObserver).onCompleted();
+			}
+		}
+
+		@Nested
+		class OnFailure {
+
+			private final RuntimeException error = new RuntimeException();
+
+			@BeforeEach
+			void init() {
+				givenGrpcCallCompletedSuccessfully();
+				doThrow(error).when(service).sendEingang(any(), any());
+			}
+
+			@SuppressWarnings("ResultOfMethodCallIgnored")
+			@Test
+			void shouldCallOnError() {
+				catchThrowableOfType(RuntimeException.class, TestRouteForwarding.this::routeForwarding);
+
+				verify(requestObserver).onError(error);
+			}
+
+			@Test
+			void shouldThrowError() {
+				assertThatThrownBy(TestRouteForwarding.this::routeForwarding).isSameAs(error);
+			}
+		}
+
+		private void givenGrpcCallCompletedSuccessfully() {
+			when(serviceStub.routeForwarding(any())).thenAnswer(invocation -> {
+				((ForwardingResponseObserver) invocation.getArgument(0)).onCompleted();
+				return requestObserver;
+			});
+		}
+
+		private void routeForwarding() {
+			service.routeForwarding(request, responseObserver);
+		}
+	}
+
+	@Nested
+	class TestSendEingang {
+
+		private final GrpcRouteForwardingRequest routeForwardingRequest = GrpcRouteForwardingRequestTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			when(vorgangService.getById(any())).thenReturn(vorgang);
+			doReturn(routeForwardingRequest).when(service).buildRouteForwardingRequest(any(), any());
+			doNothing().when(service).sendAttachments(any(), any());
+			doNothing().when(service).sendRepresentations(any(), any());
+		}
+
+		@Test
+		void shouldGetVorgangById() {
+			sendEingang();
+
+			verify(vorgangService).getById(VorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldBuildRouteForwardingRequest() {
+			sendEingang();
+
+			verify(service).buildRouteForwardingRequest(request, eingang);
+		}
+
+		@Test
+		void shouldSendForwardingRequest() {
+			sendEingang();
+
+			verify(requestObserver).onNext(routeForwardingRequest);
+		}
+
+		@Test
+		void shouldCallSendAttachments() {
+			sendEingang();
+
+			verify(service).sendAttachments(List.of(EingangTestFactory.ATTACHMENT), requestObserver);
+		}
+
+		@Test
+		void shouldCallSendRepresentations() {
+			sendEingang();
+
+			verify(service).sendRepresentations(List.of(EingangTestFactory.REPRESENTATION), requestObserver);
+		}
+
+		private void sendEingang() {
+			service.sendEingang(request, requestObserver);
+		}
+	}
+
+	@Nested
+	class TestBuildRouteForwardingRequest {
+
+		private final GrpcRouteForwarding routeForwarding = GrpcRouteForwardingTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			when(forwardingRequestMapper.toGrpcRouteForwarding(any(), any())).thenReturn(routeForwarding);
+		}
+
+		@Test
+		void shouldMapToRouteForwarding() {
+			buildRouteForwardingRequest();
+
+			verify(forwardingRequestMapper).toGrpcRouteForwarding(request, eingang);
+		}
+
+		@Test
+		void shouldReturnRouteForwardingRequest() {
+			var builtRequest = buildRouteForwardingRequest();
+
+			assertThat(builtRequest).isEqualTo(GrpcRouteForwardingRequestTestFactory.create());
+		}
+
+		private GrpcRouteForwardingRequest buildRouteForwardingRequest() {
+			return service.buildRouteForwardingRequest(request, eingang);
+		}
+	}
+
+	@Nested
+	class TestSendAttachments {
+
+		@Mock
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> fileSender;
+		@Mock
+		private InputStream inputStream;
+
+		private final IncomingFileGroup attachment = IncomingFileGroupTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			when(fileService.getUploadedFileStream(any())).thenReturn(inputStream);
+			doReturn(fileSender).when(service).createAttachmentFileSender(any(), any(), any(), any());
+			when(fileSender.send()).thenReturn(fileSender);
+		}
+
+		@Test
+		void shouldGetUploadedFileContent() {
+			sendAttachments();
+
+			verify(fileService).getUploadedFileStream(IncomingFileTestFactory.ID);
+		}
+
+		@Test
+		void shouldCallCreateAttachmentFileSender() {
+			sendAttachments();
+
+			verify(service).createAttachmentFileSender(requestObserver, IncomingFileGroupTestFactory.NAME, IncomingFileGroupTestFactory.FILE,
+					inputStream);
+		}
+
+		@Test
+		void shouldSend() {
+			sendAttachments();
+
+			verify(fileSender).send();
+		}
+
+		private void sendAttachments() {
+			service.sendAttachments(List.of(attachment), requestObserver);
+		}
+	}
+
+	@Nested
+	class TestCreateAttachmentFileSender {
+
+		@Mock
+		private InputStream inputStream;
+		@Mock
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> fileSender;
+		@Mock
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> fileSenderWithMetadata;
+		@Captor
+		private ArgumentCaptor<BiFunction<byte[], Integer, GrpcRouteForwardingRequest>> chunkBuilderCaptor;
+
+		private final byte[] chunk = RandomUtils.insecure().randomBytes(5);
+		private final GrpcRouteForwardingRequest metadataRequest = GrpcRouteForwardingRequestTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			doReturn(fileSender).when(service).createSenderWithoutMetadata(any(), any(), any());
+			doReturn(metadataRequest).when(service).buildGrpcAttachmentFile(any(), any());
+			when(fileSender.withMetaData(any())).thenReturn(fileSenderWithMetadata);
+		}
+
+		@Test
+		void shouldCallCreateSenderWithoutMetadata() {
+			createAttachmentFileSender();
+
+			verify(service).createSenderWithoutMetadata(chunkBuilderCaptor.capture(), eq(requestObserver), eq(inputStream));
+			chunkBuilderCaptor.getValue().apply(chunk, chunk.length);
+			verify(service).buildAttachmentChunk(chunk, chunk.length);
+		}
+
+		@Test
+		void shouldCallBuildGrpcAttachmentFile() {
+			createAttachmentFileSender();
+
+			verify(service).buildGrpcAttachmentFile(IncomingFileGroupTestFactory.NAME, IncomingFileGroupTestFactory.FILE);
+		}
+
+		@Test
+		void shouldSetMetaData() {
+			createAttachmentFileSender();
+
+			verify(fileSender).withMetaData(metadataRequest);
+		}
+
+		@Test
+		void shouldReturnBuiltFileSender() {
+			var returnedFileSender = createAttachmentFileSender();
+
+			assertThat(returnedFileSender).isSameAs(fileSenderWithMetadata);
+		}
+
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> createAttachmentFileSender() {
+			return service.createAttachmentFileSender(requestObserver, IncomingFileGroupTestFactory.NAME, IncomingFileGroupTestFactory.FILE,
+					inputStream);
+		}
+	}
+
+	@Nested
+	class TestBuildAttachmentChunk {
+
+		private final byte[] chunk = RandomUtils.insecure().randomBytes(5);
+
+		@BeforeEach
+		void mock() {
+			doReturn(GrpcAttachmentTestFactory.CONTENT).when(service).buildGrpcFileContent(any(), anyInt());
+		}
+
+		@Test
+		void shouldCallBuildGrpcFileContent() {
+			service.buildAttachmentChunk(chunk, chunk.length);
+
+			verify(service).buildGrpcFileContent(chunk, chunk.length);
+		}
+
+		@Test
+		void shouldReturnGrpcRouteForwardingRequest() {
+			var result = service.buildAttachmentChunk(chunk, chunk.length);
+
+			assertThat(result).isEqualTo(GrpcRouteForwardingRequestTestFactory.createWithAttachmentContent());
+		}
+	}
+
+	@Nested
+	class TestBuildGrpcAttachmentFile {
+
+		private final IncomingFile file = IncomingFileTestFactory.create();
+
+		@BeforeEach
+		void mock() {
+			when(incomingFileMapper.toAttachmentFile(any(), any())).thenReturn(GrpcAttachmentFileTestFactory.create());
+		}
+
+		@Test
+		void shouldCallIncomingFileMapper() {
+			service.buildGrpcAttachmentFile(IncomingFileGroupTestFactory.NAME, file);
+
+			verify(incomingFileMapper).toAttachmentFile(IncomingFileGroupTestFactory.NAME, file);
+		}
+
+		@Test
+		void shouldReturnAttachmentMetadataRequest() {
+			var result = service.buildGrpcAttachmentFile(IncomingFileGroupTestFactory.NAME, file);
+
+			assertThat(result).isEqualTo(GrpcRouteForwardingRequestTestFactory.createWithAttachmentMetadata());
+		}
+	}
+
+	@Nested
+	class TestSendRepresentations {
+
+		@Mock
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> fileSender;
+		@Mock
+		private InputStream inputStream;
+
+		private final IncomingFile representation = IncomingFileTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			when(fileService.getUploadedFileStream(any())).thenReturn(inputStream);
+			doReturn(fileSender).when(service).createRepresentationFileSender(any(), any(), any());
+			when(fileSender.send()).thenReturn(fileSender);
+		}
+
+		@Test
+		void shouldGetUploadedFileContent() {
+			sendRepresentations();
+
+			verify(fileService).getUploadedFileStream(IncomingFileTestFactory.ID);
+		}
+
+		@Test
+		void shouldCallCreateRepresentationFileSender() {
+			sendRepresentations();
+
+			verify(service).createRepresentationFileSender(requestObserver, representation, inputStream);
+		}
+
+		@Test
+		void shouldSend() {
+			sendRepresentations();
+
+			verify(fileSender).send();
+		}
+
+		private void sendRepresentations() {
+			service.sendRepresentations(List.of(representation), requestObserver);
+		}
+	}
+
+	@Nested
+	class TestCreateRepresentationFileSender {
+
+		@Mock
+		private InputStream inputStream;
+		@Mock
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> fileSender;
+		@Mock
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> fileSenderWithMetadata;
+		@Captor
+		private ArgumentCaptor<BiFunction<byte[], Integer, GrpcRouteForwardingRequest>> chunkBuilderCaptor;
+
+		private final byte[] chunk = RandomUtils.insecure().randomBytes(5);
+		private final GrpcRouteForwardingRequest metadataRequest = GrpcRouteForwardingRequestTestFactory.create();
+		private final IncomingFile incomingFile = IncomingFileTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			doReturn(fileSender).when(service).createSenderWithoutMetadata(any(), any(), any());
+			doReturn(metadataRequest).when(service).buildGrpcRepresentationFile(any());
+			when(fileSender.withMetaData(any())).thenReturn(fileSenderWithMetadata);
+		}
+
+		@Test
+		void shouldCallCreateSenderWithoutMetadata() {
+			createRepresentationFileSender();
+
+			verify(service).createSenderWithoutMetadata(chunkBuilderCaptor.capture(), eq(requestObserver), eq(inputStream));
+			chunkBuilderCaptor.getValue().apply(chunk, chunk.length);
+			verify(service).buildRepresentationChunk(chunk, chunk.length);
+		}
+
+		@Test
+		void shouldCallBuildGrpcRepresentationFile() {
+			createRepresentationFileSender();
+
+			verify(service).buildGrpcRepresentationFile(incomingFile);
+		}
+
+		@Test
+		void shouldSetMetaData() {
+			createRepresentationFileSender();
+
+			verify(fileSender).withMetaData(metadataRequest);
+		}
+
+		@Test
+		void shouldReturnBuiltFileSender() {
+			var returnedFileSender = createRepresentationFileSender();
+
+			assertThat(returnedFileSender).isSameAs(fileSenderWithMetadata);
+		}
+
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> createRepresentationFileSender() {
+			return service.createRepresentationFileSender(requestObserver, incomingFile, inputStream);
+		}
+	}
+
+	@Nested
+	class TestCreateSenderWithoutMetadata {
+
+		private MockedStatic<GrpcFileUploadUtils> grpcFileUploadUtilsMock;
+		@Mock
+		private BiFunction<byte[], Integer, GrpcRouteForwardingRequest> chunkBuilder;
+		@Mock
+		private CallStreamObserver<GrpcRouteForwardingRequest> requestCallStreamObserver;
+		@Mock
+		private InputStream inputStream;
+		@Mock
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> fileSender;
+		@Mock
+		private StreamObserver<GrpcRouteForwardingResponse> responseObserver;
+		@Captor
+		private ArgumentCaptor<Function<StreamObserver<GrpcRouteForwardingResponse>, CallStreamObserver<GrpcRouteForwardingRequest>>> reqObserverBuilderCaptor;
+
+		@BeforeEach
+		void init() {
+			grpcFileUploadUtilsMock = mockStatic(GrpcFileUploadUtils.class);
+			grpcFileUploadUtilsMock.when(() -> GrpcFileUploadUtils.createSender(any(), any(), any(), anyBoolean())).thenReturn(fileSender);
+		}
+
+		@AfterEach
+		void tearDown() {
+			grpcFileUploadUtilsMock.close();
+		}
+
+		@Test
+		void shouldCreateFileSender() {
+			createSenderWithoutMetadata();
+
+			grpcFileUploadUtilsMock
+					.verify(() -> GrpcFileUploadUtils.createSender(eq(chunkBuilder), eq(inputStream), reqObserverBuilderCaptor.capture(), eq(false)));
+			assertThat(reqObserverBuilderCaptor.getValue().apply(responseObserver)).isSameAs(requestCallStreamObserver);
+		}
+
+		@Test
+		void shouldReturnCreatedFileSender() {
+			var returnedFileSender = createSenderWithoutMetadata();
+
+			assertThat(returnedFileSender).isSameAs(fileSender);
+		}
+
+		private FileSender<GrpcRouteForwardingRequest, GrpcRouteForwardingResponse> createSenderWithoutMetadata() {
+			return service.createSenderWithoutMetadata(chunkBuilder, requestCallStreamObserver, inputStream);
+		}
+	}
+
+	@Nested
+	class TestBuildRepresentationChunk {
+
+		private final byte[] chunk = RandomUtils.insecure().randomBytes(5);
+
+		@BeforeEach
+		void mock() {
+			doReturn(GrpcRepresentationTestFactory.CONTENT).when(service).buildGrpcFileContent(any(), anyInt());
+		}
+
+		@Test
+		void shouldCallBuildGrpcFileContent() {
+			service.buildRepresentationChunk(chunk, chunk.length);
+
+			verify(service).buildGrpcFileContent(chunk, chunk.length);
+		}
+
+		@Test
+		void shouldReturnGrpcRouteForwardingRequest() {
+			var result = service.buildRepresentationChunk(chunk, chunk.length);
+
+			assertThat(result).isEqualTo(GrpcRouteForwardingRequestTestFactory.createWithRepresentationContent());
+		}
+	}
+
+	@Nested
+	class TestBuildGrpcFileContent {
+
+		@Nested
+		class TestOnEndOfFile {
+
+			@Test
+			void shouldBuildEndOfFileChunk() {
+				var fileContent = service.buildGrpcFileContent(new byte[0], -1);
+
+				assertThat(fileContent).isEqualTo(GrpcFileContentTestFactory.createEndOfFile());
+			}
+		}
+
+		@Nested
+		class TestOnContentProvided {
+
+			@Test
+			void shouldBuildEndOfFileChunk() {
+				var fileContent = service.buildGrpcFileContent(GrpcFileContentTestFactory.CONTENT, GrpcFileContentTestFactory.CONTENT.length);
+
+				assertThat(fileContent).isEqualTo(GrpcFileContentTestFactory.create());
+			}
+		}
+	}
+
+	@Nested
+	class TestBuildGrpcRepresentationFile {
+
+		private final IncomingFile file = IncomingFileTestFactory.create();
+
+		@BeforeEach
+		void mock() {
+			when(incomingFileMapper.toRepresentationFile(any())).thenReturn(GrpcRepresentationFileTestFactory.create());
+		}
+
+		@Test
+		void shouldCallIncomingFileMapper() {
+			service.buildGrpcRepresentationFile(file);
+
+			verify(incomingFileMapper).toRepresentationFile(file);
+		}
+
+		@Test
+		void shouldReturnRepresentationMetadataRequest() {
+			var result = service.buildGrpcRepresentationFile(file);
+
+			assertThat(result).isEqualTo(GrpcRouteForwardingRequestTestFactory.createWithRepresentationMetadata());
+		}
+	}
+
+	@Nested
+	class TestWaitForCompletion {
+
+		@Mock
+		private CompletableFuture<Void> future;
+
+		@SneakyThrows
+		@Test
+		void shouldGetFromFuture() {
+			waitForCompletion();
+
+			verify(future).get(2, TimeUnit.MINUTES);
+		}
+
+		@Nested
+		class TestOnInterruptedException {
+
+			private final InterruptedException exception = new InterruptedException();
+
+			@BeforeEach
+			@SneakyThrows
+			void mock() {
+				when(future.get(anyLong(), any())).thenThrow(exception);
+			}
+
+			@Test
+			void shouldThrowTechnicalException() {
+				assertThrows(TechnicalException.class, TestWaitForCompletion.this::waitForCompletion);
+			}
+
+			@Test
+			void shouldInterruptThread() {
+				try {
+					waitForCompletion();
+				} catch (TechnicalException e) {
+					// expected
+				}
+
+				assertThat(Thread.currentThread().isInterrupted()).isTrue();
+			}
+		}
+
+		@Nested
+		class TestOnExecutionException {
+
+			private final ExecutionException exception = new ExecutionException(new Exception());
+
+			@BeforeEach
+			@SneakyThrows
+			void mock() {
+				when(future.get(anyLong(), any())).thenThrow(exception);
+			}
+
+			@Test
+			void shouldThrowTechnicalException() {
+				assertThrows(TechnicalException.class, TestWaitForCompletion.this::waitForCompletion);
+			}
+		}
+
+		@Nested
+		class TestOnTimeoutException {
+
+			private final TimeoutException exception = new TimeoutException();
+
+			@BeforeEach
+			@SneakyThrows
+			void mock() {
+				when(future.get(anyLong(), any())).thenThrow(exception);
+			}
+
+			@Test
+			void shouldThrowTechnicalException() {
+				assertThrows(TechnicalException.class, TestWaitForCompletion.this::waitForCompletion);
+			}
+		}
+
+		private void waitForCompletion() {
+			service.waitForCompletion(future);
+		}
+	}
+
+	@Nested
+	class ForwardingResponseObserverTest {
+
+		@Mock
+		private CompletableFuture<Void> future;
+		private ForwardingResponseObserver responseObserver;
+
+		@BeforeEach
+		void init() {
+			responseObserver = new ForwardingResponseObserver(future);
+		}
+
+		@Test
+		void shouldCompleteExceptionallyOnError() {
+			var error = new Throwable();
+
+			responseObserver.onError(error);
+
+			verify(future).completeExceptionally(error);
+		}
+
+		@Test
+		void shouldCompleteOnCompleted() {
+			responseObserver.onCompleted();
+
+			verify(future).complete(null);
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRequestMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRequestMapperTest.java
index 715529e268ded4133f6e9962fada6f8ce2c8ca35..ffa5197108a4c22c78753140c2f2dd3da9d74be5 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRequestMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRequestMapperTest.java
@@ -32,14 +32,26 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
 import org.mockito.Spy;
 
+import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding;
 import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.vorgang.Eingang;
+import de.ozgcloud.vorgang.vorgang.EingangMapper;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.vorgang.GrpcEingang;
+import de.ozgcloud.vorgang.vorgang.GrpcEingangTestFactory;
 import de.ozgcloud.vorgang.vorgang.redirect.ForwardingRequestMapper.CommandBodyFields;
 
 class ForwardingRequestMapperTest {
 
+	@Mock
+	private EingangMapper eingangMapper;
 	@Spy
+	@InjectMocks
 	private ForwardingRequestMapper mapper = Mappers.getMapper(ForwardingRequestMapper.class);
 	private final Map<String, Object> bodyObject = Map.of(
 			CommandBodyFields.ORGANISATION_EINHEIT_ID, OrganisationEinheitTestFactory.ID,
@@ -118,4 +130,65 @@ class ForwardingRequestMapperTest {
 			return mapper.toAddress(bodyObject);
 		}
 	}
+
+	@Nested
+	class TestToGrpcRouteForwarding {
+
+		private final ForwardingRequest request = ForwardingRequestTestFactory.create();
+		private final Eingang eingang = EingangTestFactory.create();
+		private final GrpcEingang grpcEingang = GrpcEingangTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			doReturn(GrpcRouteCriteriaTestFactory.create()).when(mapper).toGrpcRouteCriteria(any());
+			when(eingangMapper.toGrpc(any())).thenReturn(grpcEingang);
+		}
+
+		@Test
+		void shouldCallEingangMapper() {
+			map();
+
+			verify(eingangMapper).toGrpc(eingang);
+		}
+
+		@Test
+		void shouldMapToGrpcRouteCriteria() {
+			map();
+
+			verify(mapper).toGrpcRouteCriteria(request);
+		}
+
+		@Test
+		void shouldMapToGrpcEingangStub() {
+			map();
+
+			verify(mapper).toGrpcEingangStub(grpcEingang);
+		}
+
+		@Test
+		void shouldMapToGrpcRouteForwarding() {
+			var mapped = map();
+
+			assertThat(mapped).isEqualTo(GrpcRouteForwardingTestFactory.create());
+		}
+
+		private GrpcRouteForwarding map() {
+			return mapper.toGrpcRouteForwarding(request, eingang);
+		}
+	}
+
+	@Nested
+	class TestToGrpcRouteCriteria {
+
+		@Test
+		void shouldMap() {
+			var mapped = map();
+
+			assertThat(mapped).isEqualTo(GrpcRouteCriteriaTestFactory.create());
+		}
+
+		private GrpcRouteCriteria map() {
+			return mapper.toGrpcRouteCriteria(ForwardingRequestTestFactory.create());
+		}
+	}
 }
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java
index 1b864c7a9ab50c247178efd8d1346e87aff1e4f5..326cf45ddf0f6ea612311f599880cdb81e231d43 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java
@@ -64,19 +64,16 @@ class ForwardingServiceTest {
 	private ForwardingService service;
 	@Mock
 	private ForwardingRepository repository;
-
 	@Mock
 	private ZipBuilderService zipService;
-
 	@Mock
 	private MailService mailService;
-
 	@Mock
 	private VorgangService vorgangService;
-
 	@Mock
 	private StatusService statusService;
-
+	@Mock
+	private ForwardingRemoteService remoteService;
 	@Mock
 	private ApplicationEventPublisher publisher;
 
@@ -626,11 +623,24 @@ class ForwardingServiceTest {
 	@Nested
 	class TestForward {
 
+		private final ForwardingRequest request = ForwardingRequestTestFactory.create();
+
 		@Test
 		void shouldSetStatusToWeitergeleitet() {
-			service.forward(ForwardingRequestTestFactory.create());
+			forward();
 
 			verify(statusService).setStatusToWeitergeleitet(VorgangTestFactory.ID, VorgangTestFactory.VERSION);
 		}
+
+		@Test
+		void shouldCallRemoteService() {
+			forward();
+
+			verify(remoteService).forward(request);
+		}
+
+		private void forward() {
+			service.forward(request);
+		}
 	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcAttachmentFileTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcAttachmentFileTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c954a3e170cdf1bafb583cb5cc59933637f665a
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcAttachmentFileTestFactory.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile;
+import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile.Builder;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroupTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+
+public class GrpcAttachmentFileTestFactory {
+
+	public static final String GROUP_NAME = IncomingFileGroupTestFactory.NAME;
+
+	public static GrpcAttachmentFile create() {
+		return createBuilder().build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcAttachmentFile.newBuilder()
+				.setGroupName(GROUP_NAME)
+				.setFileName(IncomingFileTestFactory.NAME)
+				.setContentType(IncomingFileTestFactory.CONTENT_TYPE_STR)
+				.setVendorId(IncomingFileTestFactory.VENDOR_ID)
+				.setSize(IncomingFileTestFactory.SIZE);
+	}
+
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcAttachmentTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcAttachmentTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e0e278a9d017593627fa279c7837dfaa0d221c7
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcAttachmentTestFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import de.ozgcloud.eingang.forwarding.GrpcAttachment;
+import de.ozgcloud.eingang.forwarding.GrpcAttachmentFile;
+import de.ozgcloud.eingang.forwarding.GrpcFileContent;
+
+public class GrpcAttachmentTestFactory {
+
+	public static final GrpcAttachmentFile FILE = GrpcAttachmentFileTestFactory.create();
+	public static final GrpcFileContent CONTENT = GrpcFileContentTestFactory.create();
+
+	public static GrpcAttachment createWithFile() {
+		return GrpcAttachment.newBuilder()
+				.setFile(FILE)
+				.build();
+	}
+
+	public static GrpcAttachment createWithContent() {
+		return GrpcAttachment.newBuilder()
+				.setContent(CONTENT)
+				.build();
+	}
+
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcEingangStubTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcEingangStubTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..6cdd06a4a1b2ad6af5d26bd3265c76ce2890cba6
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcEingangStubTestFactory.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import de.ozgcloud.eingang.forwarding.GrpcEingangStub;
+import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory;
+import de.ozgcloud.vorgang.vorgang.GrpcAntragstellerTestFactory;
+import de.ozgcloud.vorgang.vorgang.GrpcEingangHeaderTestFactory;
+
+class GrpcEingangStubTestFactory {
+
+	public static GrpcEingangStub create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcEingangStub.Builder createBuilder() {
+		return GrpcEingangStub.newBuilder()
+				.setHeader(GrpcEingangHeaderTestFactory.create())
+				.setAntragsteller(GrpcAntragstellerTestFactory.create())
+				.setFormData(GrpcFormDataTestFactory.create());
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcFileContentTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcFileContentTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..c37286a4df81c814c805fd2a6c05ac84a9741e68
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcFileContentTestFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import org.apache.commons.lang3.RandomUtils;
+
+import com.google.protobuf.ByteString;
+
+import de.ozgcloud.eingang.forwarding.GrpcFileContent;
+import de.ozgcloud.eingang.forwarding.GrpcFileContent.Builder;
+
+public class GrpcFileContentTestFactory {
+
+	public static final boolean IS_END_OF_FILE = false;
+	public static final byte[] CONTENT = RandomUtils.insecure().randomBytes(10);;
+
+	public static GrpcFileContent create() {
+		return createBuilder().build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcFileContent.newBuilder()
+				.setContent(ByteString.copyFrom(CONTENT))
+				.setIsEndOfFile(IS_END_OF_FILE);
+	}
+
+	public static GrpcFileContent createEndOfFile() {
+		return GrpcFileContent.newBuilder().setIsEndOfFile(true).build();
+	}
+
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRepresentationFileTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRepresentationFileTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d832cbc58b40bb3a68f0ac65d28d557c563934d2
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRepresentationFileTestFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import de.ozgcloud.eingang.forwarding.GrpcRepresentationFile;
+import de.ozgcloud.eingang.forwarding.GrpcRepresentationFile.Builder;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+
+public class GrpcRepresentationFileTestFactory {
+
+	public static GrpcRepresentationFile create() {
+		return createBuilder().build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcRepresentationFile.newBuilder()
+				.setFileName(IncomingFileTestFactory.NAME)
+				.setContentType(IncomingFileTestFactory.CONTENT_TYPE_STR)
+				.setVendorId(IncomingFileTestFactory.VENDOR_ID)
+				.setSize(IncomingFileTestFactory.SIZE);
+	}
+
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRepresentationTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRepresentationTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4dce5a27e1c366229b9ad697e79717ba73c09a81
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRepresentationTestFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import de.ozgcloud.eingang.forwarding.GrpcFileContent;
+import de.ozgcloud.eingang.forwarding.GrpcRepresentation;
+import de.ozgcloud.eingang.forwarding.GrpcRepresentationFile;
+
+public class GrpcRepresentationTestFactory {
+
+	public static final GrpcRepresentationFile FILE = GrpcRepresentationFileTestFactory.create();
+	public static final GrpcFileContent CONTENT = GrpcFileContentTestFactory.create();
+
+	public static GrpcRepresentation createWithFile() {
+		return GrpcRepresentation.newBuilder()
+				.setFile(FILE)
+				.build();
+	}
+
+	public static GrpcRepresentation createWithContent() {
+		return GrpcRepresentation.newBuilder()
+				.setContent(CONTENT)
+				.build();
+	}
+}
diff --git a/vorgang-manager-interface/src/main/protobuf/route-forwarding.proto b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteCriteriaTestFactory.java
similarity index 66%
rename from vorgang-manager-interface/src/main/protobuf/route-forwarding.proto
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteCriteriaTestFactory.java
index aeb0eefd8c8dd8447e8e26f88bff45b4ea35f630..e28c74034003854c9467922062a80a86f24185f8 100644
--- a/vorgang-manager-interface/src/main/protobuf/route-forwarding.proto
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteCriteriaTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,19 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-syntax = "proto3";
+package de.ozgcloud.vorgang.vorgang.redirect;
 
-package de.ozgcloud.eingang.forwarder;
+import de.ozgcloud.eingang.forwarding.GrpcRouteCriteria;
 
-import "route-forwarding.model.proto";
+class GrpcRouteCriteriaTestFactory {
 
-option java_multiple_files = true;
-option java_package = "de.ozgcloud.eingang.forwarder";
-option java_outer_classname = "RouteForwardingProto";
-
-service RouteForwardingService {
-
-	rpc RouteForwarding(GrpcRouteForwardingRequest) returns (GrpcRouteForwardingResponse) {
+	public static GrpcRouteCriteria create() {
+		return createBuilder().build();
 	}
 
-}
\ No newline at end of file
+	public static GrpcRouteCriteria.Builder createBuilder() {
+		return GrpcRouteCriteria.newBuilder()
+				.setOrganisationEinheitId(OrganisationEinheitTestFactory.ID);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteForwardingRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteForwardingRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d463347d23cf97551855d460b655ea3da710524
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteForwardingRequestTestFactory.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2025 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.vorgang.redirect;
+
+import de.ozgcloud.eingang.forwarding.GrpcAttachment;
+import de.ozgcloud.eingang.forwarding.GrpcRepresentation;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwardingRequest;
+
+class GrpcRouteForwardingRequestTestFactory {
+
+	public static final GrpcAttachment ATTACHMENT_METADATA = GrpcAttachmentTestFactory.createWithFile();
+	public static final GrpcAttachment ATTACHMENT_CONTENT = GrpcAttachmentTestFactory.createWithContent();
+	public static final GrpcRepresentation REPRESENTATION_METADATA = GrpcRepresentationTestFactory.createWithFile();
+	public static final GrpcRepresentation REPRESENTATION_CONTENT = GrpcRepresentationTestFactory.createWithContent();
+
+	public static GrpcRouteForwardingRequest create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcRouteForwardingRequest.Builder createBuilder() {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setRouteForwarding(GrpcRouteForwardingTestFactory.create());
+	}
+
+	public static GrpcRouteForwardingRequest createWithAttachmentMetadata() {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setAttachment(ATTACHMENT_METADATA)
+				.build();
+	}
+
+	public static GrpcRouteForwardingRequest createWithAttachmentContent() {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setAttachment(ATTACHMENT_CONTENT)
+				.build();
+	}
+
+	public static GrpcRouteForwardingRequest createWithRepresentationMetadata() {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setRepresentation(REPRESENTATION_METADATA)
+				.build();
+	}
+
+	public static GrpcRouteForwardingRequest createWithRepresentationContent() {
+		return GrpcRouteForwardingRequest.newBuilder()
+				.setRepresentation(REPRESENTATION_CONTENT)
+				.build();
+	}
+}
diff --git a/vorgang-manager-interface/src/main/protobuf/route-forwarding.model.proto b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteForwardingTestFactory.java
similarity index 60%
rename from vorgang-manager-interface/src/main/protobuf/route-forwarding.model.proto
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteForwardingTestFactory.java
index 46961d480f78f8a30591492b272e7ecf1329a4af..badf9c7b5c9aa3536c559cf51d09540ab2696c45 100644
--- a/vorgang-manager-interface/src/main/protobuf/route-forwarding.model.proto
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcRouteForwardingTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,28 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-syntax = "proto3";
+package de.ozgcloud.vorgang.vorgang.redirect;
 
-package de.ozgcloud.eingang.forwarder;
+import de.ozgcloud.eingang.forwarding.GrpcRouteForwarding;
 
-import "vorgang.model.proto";
+class GrpcRouteForwardingTestFactory {
 
-option java_multiple_files = true;
-option java_package = "de.ozgcloud.eingang.forwarding";
-option java_outer_classname = "RouteForwardingModelProto";
+	public static GrpcRouteForwarding create() {
+		return createBuilder().build();
+	}
 
-
-message GrpcRouteForwardingRequest {
-	GrpcRouteCriteria routeCriteria = 1;
-	de.ozgcloud.vorgang.vorgang.GrpcEingang eingang = 5;
-}
-
-message GrpcRouteForwardingResponse {
-	
+	public static GrpcRouteForwarding.Builder createBuilder() {
+		return GrpcRouteForwarding.newBuilder()
+				.setRouteCriteria(GrpcRouteCriteriaTestFactory.create())
+				.setEingangStub(GrpcEingangStubTestFactory.create());
+	}
 }
-
-message GrpcRouteCriteria {
-	string gemeindeSchluessel = 1;
-	string webserviceUrl = 2;
-	string organisationseinheitenId = 3;
-}
\ No newline at end of file
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataTestFactory.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataTestFactory.java
index b715c9098e9cc4134bcd1281a403563c4641dce5..760f1e90310ba7a316c82824a0ca625bed204d43 100644
--- a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataTestFactory.java
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataTestFactory.java
@@ -34,6 +34,7 @@ public class GrpcFormDataTestFactory {
 
 	public static Builder createBuilder() {
 		return GrpcFormData.newBuilder()
-				.addField(GrpcFormFieldTestFactory.create());
+				.addField(GrpcFormFieldTestFactory.create())
+				.addForm(GrpcSubFormTestFactory.create());
 	}
 }