diff --git a/README.md b/README.md
index c85718ee13066ca8a689c63e7e3ce529559477e3..96c81e1bfc4fb8ef849e90497aece7f47d3673b1 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,23 @@
 # Fachstellen-Proxy
 
+Der Fachstellen-Proxy nimmt HTTP Requests von der Fachstelle entgegen, mappt diese auf gRPC
+und leitet sie an den Zufi- (Fachstellenregistrierung) bzw. Collaboration-Manager
+(Fachstellenbeteiligung) weiter. Zum Protokollmapping von HTTP auf gRPC wird die Bibliothek 
+[gRPC-Gateway](https://grpc-ecosystem.github.io/grpc-gateway/) verwendet. Dadurch können
+die HTTP-Endpunkte inkl. des Mappings größtenteils automatisch aus proto-Dateien generiert werden.
+
+Requests zur Fachstellenregistrierung werden an die unter config.grpc.registration.server.url
+eingetragene URL (bzw. localhost:50052, wenn config.grpc.mock = true) weitergeleitet.
+
+Requests zur Fachstellenbeteiligung (z.B. FindVorgang) werden zunächst an den CollaborationRouter
+weitergeleitet. Das ist ein Proxy-eigener gRPC-Server, der auf localhost und dem unter
+config.grpc.collaboration.router.port eingetragenen Port läuft. Dort wird die Adresse des
+Ziel-Collaboration-Managers aus dem Requestpayload (z.B. aus der VorgangId) extrahiert. Der Port
+des Ziel-Collaboration-Managers ist konstant und wird unter config.grpc.collaboration.server.port
+festgelegt (bzw. auf 50052 gesetzt, wenn config.grpc.mock = true). Anschließend leitet der 
+CollaborationRouter die gRPC Request an die URL weiter, die aus der extrahierten Adresse und dem 
+Port zusammengesetzt wird.
+
 ## Getting Started
 
 ### Dependencies installieren
@@ -37,11 +55,19 @@ go run cmd/fachstellen-proxy/main.go
 [Config-Datei](./config/config.yml)
 
 ```
-server:
-  port: Port des HTTP Servers (int)
+http:
+  server:
+    port: Port des HTTP Gateways (int)
 grpc:
-  mock: lokalen gRPC Server mocken (bool)
-  url: URL des Ziel-gRPC-Servers im host:port Format (string)
+  mock: gRPC Registration und Collaboration Server mocken (bool)
+  collaboration:
+    server:
+      port: Port des gRPC Collaboration Servers (int)
+    router: 
+      port: Port des gRPC Collaboration Routers (int)
+  registration:
+    server:
+      url: URL des gRPC Registration Servers im host:port Format (string)
 logging:
   level: "ERROR" | "WARN" | "INFO" | "DEBUG"
 ```
\ No newline at end of file
diff --git a/api/gateway-config.yml b/api/gateway-config.yml
index b158d6f06fff7338ef972c3eb233f64f9ee2f2f6..4b88f29c962d65f5b2ab3cf329aa1ba8951a5127 100644
--- a/api/gateway-config.yml
+++ b/api/gateway-config.yml
@@ -3,6 +3,8 @@ config_version: 3
 
 http:
   rules:
-    - selector: de.ozgcloud.zufi.grpc.fachstelle.FachstelleRegistrationService.Register
+    - selector: de.ozgcloud.fachstellenproxy.FachstelleRegistrationService.Register
       post: /api/fachstellen
       body: "*"
+    - selector: de.ozgcloud.fachstellenproxy.CollaborationService.FindVorgang
+      get: /api/vorgang/{vorgangId}/{samlToken}
diff --git a/api/openapi-config.yml b/api/openapi-config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f32a4dd6e5c5a8d5629b450e15a881fc7048c522
--- /dev/null
+++ b/api/openapi-config.yml
@@ -0,0 +1,89 @@
+openapiOptions:
+  file:
+    - file: "fachstelleregistration.proto"
+      option:
+        info:
+          title: Fachstelleregistration Proxy API
+          license:
+            name: EUPL 1.2
+            url: https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+          version: "1.0"
+        schemes:
+          - HTTP
+          - HTTPS
+        consumes:
+          - application/json
+        produces:
+          - application/json
+        responses:
+          "400":
+            description: Returned when the request payload is not suitable.
+            schema:
+              jsonSchema:
+                type:
+                  - STRING
+    - file: "collaboration.proto"
+      option:
+        info:
+          title: Collaboration Proxy API
+          license:
+            name: EUPL 1.2
+            url: https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+          version: "1.0"
+        schemes:
+          - HTTP
+          - HTTPS
+        consumes:
+          - application/json
+        produces:
+          - application/json
+        responses:
+          "403":
+            description: Returned when the user does not have permission to access the resource.
+          "404":
+            description: Returned when the resource does not exist.
+            schema:
+              jsonSchema:
+                type:
+                  - STRING
+  service:
+    - service: de.ozgcloud.fachstellenproxy.FachstelleRegistrationService
+      option:
+        description: "Service to proxy between Fachstelle and ZufiManager in OZG-Cloud"
+    - service: de.ozgcloud.fachstellenproxy.CollaborationService
+      option:
+        description: "Service to proxy between Fachstelle and CollaborationManager in OZG-Cloud"
+  method:
+    - method: de.ozgcloud.fachstellenproxy.FachstelleRegistrationService.Register
+      option:
+        description: "Register new fachstelle"
+        summary: "Summary: Register rpc"
+        responses:
+          "200":
+            description: Returns empty response
+          "400":
+            description: Returned when the request payload is not suitable.
+          "503":
+            description: Returned when the resource is temporarily unavailable.
+    - method: de.ozgcloud.fachstellenproxy.CollaborationService.FindVorgang
+      option:
+        description: "Find vorgang by its id"
+        summary: "Summary: FindVorgang rpc"
+        responses:
+          "200":
+            description: Returns the vorgang
+          "503":
+            description: Returned when the resource is temporarily unavailable.
+          "404":
+            description: Returned when the resource does not exist.
+    - method: de.ozgcloud.fachstellenproxy.CollaborationService.GetFileContent
+      option:
+        description: "Get file content by file id"
+        summary: "Summary: GetFileContent rpc"
+        responses:
+          "200":
+            description: Returns the file content
+          "503":
+            description: Returned when the resource is temporarily unavailable.
+          "404":
+            description: Returned when the resource does not exist.
\ No newline at end of file
diff --git a/api/proto/collaboration.model.proto b/api/proto/collaboration.model.proto
new file mode 100644
index 0000000000000000000000000000000000000000..b51dbbdf794130e400f0cea360c13822cb33e677
--- /dev/null
+++ b/api/proto/collaboration.model.proto
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package de.ozgcloud.fachstellenproxy;
+
+option go_package = "de.ozgcloud.fachstellenproxy";
+
+message GrpcFindVorgangRequest {
+  string vorgangId = 1;
+  string samlToken = 2;
+}
+
+message GrpcFindVorgangResponse {
+  GrpcVorgang vorgang = 1;
+}
+
+message GrpcVorgang {
+  string id = 1;
+  int64 version = 2;
+  string vorgangName = 3;
+  string vorgangNummer = 4;
+
+  GrpcVorgangHeader header = 5;
+  GrpcEingang eingang = 6;
+  GrpcCollaborationRequest collaborationRequest = 7;
+}
+
+message GrpcVorgangHeader {
+  string createdAt = 1;
+  string aktenzeichen = 2;
+}
+
+message GrpcCollaborationRequest {
+  string title = 1;
+  string text = 2;
+}
+
+message GrpcEingang {
+  GrpcAntragsteller antragsteller = 1;
+
+  GrpcFormData formData = 2;
+
+  repeated GrpcFileGroup attachments = 3;
+  repeated GrpcFile representations = 4;
+}
+
+message GrpcFileGroup {
+  string name = 1;
+  repeated GrpcFile files = 2;
+}
+
+message GrpcFile {
+  string id = 1;
+  string vendorId = 2;
+  string name = 3;
+  string contentType = 4;
+  int64 size = 5;
+}
+
+message GrpcAntragsteller {
+  string firmaName = 1;
+  string anrede = 2;
+  string nachname = 3;
+  string vorname = 4;
+  string geburtsdatum = 5;
+  string geburtsort = 7;
+  string geburtsname = 8;
+  string email = 9;
+  string telefon = 10;
+  string strasse = 11;
+  string hausnummer = 12;
+  string plz = 13;
+  string ort = 14;
+
+  GrpcFormData otherData = 15;
+}
+
+message GrpcFormData {
+  repeated GrpcSubFormData formData = 1;
+}
+
+message GrpcSubForm {
+  string name = 1;
+  string label = 2;
+  repeated GrpcSubFormData formData = 3;
+}
+
+message GrpcSubFormData {
+  oneof data {
+    GrpcFormField field = 1;
+    GrpcSubForm form = 2;
+  }
+}
+
+message GrpcFormField {
+  string name = 1;
+  string label = 2;
+  string value = 3;
+}
+
+message GrpcGetFileContentRequest {
+  string samlToken = 1;
+  string id = 2;
+}
+
+message GrpcGetFileContentResponse {
+  bytes fileContent = 1;
+}
\ No newline at end of file
diff --git a/api/proto/collaboration.proto b/api/proto/collaboration.proto
new file mode 100644
index 0000000000000000000000000000000000000000..fac2e32c3e532a0340a5d0dcf2a0000ef512f7ee
--- /dev/null
+++ b/api/proto/collaboration.proto
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package de.ozgcloud.fachstellenproxy;
+
+import "collaboration.model.proto";
+
+option go_package = "de.ozgcloud.fachstellenproxy";
+
+service CollaborationService {
+  rpc FindVorgang(GrpcFindVorgangRequest) returns (GrpcFindVorgangResponse);
+
+  rpc GetFileContent(GrpcGetFileContentRequest) returns (stream GrpcGetFileContentResponse);
+}
\ No newline at end of file
diff --git a/api/proto/fachstelleregistration.model.proto b/api/proto/fachstelleregistration.model.proto
index 9b9a1e18d742a8a38e340408f25a70a19b08e437..7ade3294fdd6e7bdf164fc784574f0d702eba655 100644
--- a/api/proto/fachstelleregistration.model.proto
+++ b/api/proto/fachstelleregistration.model.proto
@@ -25,9 +25,9 @@
 
 syntax = "proto3";
 
-package de.ozgcloud.zufi.grpc.fachstelle;
+package de.ozgcloud.fachstellenproxy;
 
-option go_package = "de.ozgcloud.zufi.grpc.fachstelle";
+option go_package = "de.ozgcloud.fachstellenproxy";
 
 message GrpcFachstelleRegistrationRequest {
   GrpcFachstelle fachstelle = 1;
diff --git a/api/proto/fachstelleregistration.proto b/api/proto/fachstelleregistration.proto
index 48fd82241469cb8aad746543cb0d91aecacd43ad..f354c0f47b3ffd5ffb324536c6aaf1b172a36f29 100644
--- a/api/proto/fachstelleregistration.proto
+++ b/api/proto/fachstelleregistration.proto
@@ -25,11 +25,11 @@
 
 syntax = "proto3";
 
-package de.ozgcloud.zufi.grpc.fachstelle;
+package de.ozgcloud.fachstellenproxy;
 
 import "fachstelleregistration.model.proto";
 
-option go_package = "de.ozgcloud.zufi.grpc.fachstelle";
+option go_package = "de.ozgcloud.fachstellenproxy";
 
 service FachstelleRegistrationService {
   rpc Register(GrpcFachstelleRegistrationRequest) returns (GrpcFachstelleRegistrationResponse);
diff --git a/buf.gen.yaml b/buf.gen.yaml
index 611034ed3c665110980e0ab16e84936152522a7a..21d5c631f37d8df3cddb48450fd1a576b977b7cd 100644
--- a/buf.gen.yaml
+++ b/buf.gen.yaml
@@ -14,4 +14,9 @@ plugins:
       - paths=source_relative
       - grpc_api_configuration=api/gateway-config.yml
   - plugin: openapiv2
-    out: gen/openapiv2
\ No newline at end of file
+    out: gen/openapiv2
+    opt:
+      - allow_merge=true
+      - merge_file_name=openapiv2.json
+      - grpc_api_configuration=api/gateway-config.yml
+      - openapi_configuration=api/openapi-config.yml
\ No newline at end of file
diff --git a/cmd/fachstellen-proxy/main.go b/cmd/fachstellen-proxy/main.go
index c6a993e9a18aedf3d364e250ff3e18c62cf8026c..2cf1bef5238d5f60eaf916ba640a3ea3d714931a 100644
--- a/cmd/fachstellen-proxy/main.go
+++ b/cmd/fachstellen-proxy/main.go
@@ -40,5 +40,6 @@ func main() {
 		go mock.StartGrpcServer()
 	}
 
-	server.StartHttpGateway(conf)
+	go server.StartCollaborationRouter()
+	server.StartHttpGateway()
 }
diff --git a/config/config.yml b/config/config.yml
index 8605b248d11050d5a8ad3c71b3e41e20eb8993d6..8a80d9ff53c5aecb6d8d2ef2aa61265ac0e0dbee 100755
--- a/config/config.yml
+++ b/config/config.yml
@@ -1,6 +1,10 @@
-server:
-  port: 8082
+http:
+  server:
+    port: 8082
 grpc:
   mock: true
+  collaboration:
+    router:
+      port: 50051
 logging:
   level: "INFO"
\ No newline at end of file
diff --git a/internal/config/config.go b/internal/config/config.go
index b246c3d63d3ad026e142c890f9532722f122358e..b46e14a135880eb52874f7a20cc7dc4075873e3b 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -41,12 +41,26 @@ const (
 )
 
 type Config struct {
-	Server struct {
-		Port int `yaml:"port" envconfig:"SERVER_PORT"`
-	} `yaml:"server"`
+	Http struct {
+		Server struct {
+			Port int `yaml:"port" envconfig:"HTTP_SERVER_PORT"`
+		} `yaml:"server"`
+	} `yaml:"http"`
 	Grpc struct {
-		Mock bool   `yaml:"mock" envconfig:"GRPC_MOCK"`
-		Url  string `yaml:"url" envconfig:"GRPC_URL"`
+		Mock          bool `yaml:"mock" envconfig:"GRPC_MOCK"`
+		Collaboration struct {
+			Server struct {
+				Port int `yaml:"port" envconfig:"GRPC_COLLABORATION_SERVER_PORT"`
+			} `yaml:"server"`
+			Router struct {
+				Port int `yaml:"port" envconfig:"GRPC_COLLABORATION_ROUTER_PORT"`
+			} `yaml:"router"`
+		} `yaml:"collaboration"`
+		Registration struct {
+			Server struct {
+				Url string `yaml:"url" envconfig:"GRPC_REGISTRATION_SERVER_URL"`
+			} `yaml:"server"`
+		} `yaml:"registration"`
 	} `yaml:"grpc"`
 	Logging struct {
 		Level string `yaml:"level" envconfig:"LOGGING_LEVEL"`
@@ -78,8 +92,8 @@ func LoadConfig(configFilePath ...string) Config {
 		log.Fatalf("FATAL: error reading env: %v", err)
 	}
 
-	if len(config.Grpc.Url) > 0 && !ValidateGrpcUrl(config.Grpc.Url) {
-		log.Fatalf("FATAL: gRPC URL is not in host:port format")
+	if len(config.Grpc.Registration.Server.Url) > 0 && !ValidateGrpcUrl(config.Grpc.Registration.Server.Url) {
+		log.Fatalf("FATAL: gRPC Registration Server URL is not in host:port format")
 	}
 
 	return config
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index 38cd14245895c0ba67c51af3f41cd7d3faf899f9..9f615b6bc639bf66da9fb3d5070123c63b70fc83 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -37,8 +37,10 @@ func TestLoadConfig(t *testing.T) {
 		config := LoadConfig()
 
 		expectedConfig := Config{}
-		expectedConfig.Server.Port = 8080
-		expectedConfig.Grpc.Url = "localhost:50051"
+		expectedConfig.Http.Server.Port = 8080
+		expectedConfig.Grpc.Collaboration.Server.Port = 50052
+		expectedConfig.Grpc.Collaboration.Router.Port = 50051
+		expectedConfig.Grpc.Registration.Server.Url = "localhost:50052"
 		expectedConfig.Grpc.Mock = false
 		expectedConfig.Logging.Level = "DEBUG"
 
@@ -47,9 +49,11 @@ func TestLoadConfig(t *testing.T) {
 
 	t.Run("should load config from env", func(t *testing.T) {
 		envVars := map[string]string{
-			"SERVER_PORT":   "9090",
-			"GRPC_URL":      "localhost:99999",
-			"LOGGING_LEVEL": "ERROR",
+			"HTTP_SERVER_PORT":               "9090",
+			"GRPC_COLLABORATION_SERVER_PORT": "50052",
+			"GRPC_COLLABORATION_ROUTER_PORT": "50051",
+			"GRPC_REGISTRATION_SERVER_URL":   "localhost:99999",
+			"LOGGING_LEVEL":                  "ERROR",
 		}
 
 		for key, value := range envVars {
@@ -63,8 +67,10 @@ func TestLoadConfig(t *testing.T) {
 		}
 
 		expectedConfig := Config{}
-		expectedConfig.Server.Port = 9090
-		expectedConfig.Grpc.Url = "localhost:99999"
+		expectedConfig.Http.Server.Port = 9090
+		expectedConfig.Grpc.Collaboration.Server.Port = 50052
+		expectedConfig.Grpc.Collaboration.Router.Port = 50051
+		expectedConfig.Grpc.Registration.Server.Url = "localhost:99999"
 		expectedConfig.Grpc.Mock = false
 		expectedConfig.Logging.Level = "ERROR"
 
@@ -72,15 +78,26 @@ func TestLoadConfig(t *testing.T) {
 	})
 
 	t.Run("should overwrite config with env", func(t *testing.T) {
-		assert.NoError(t, os.Setenv("SERVER_PORT", "9090"), "Setenv SERVER_PORT should not return an error")
+		envVars := map[string]string{
+			"HTTP_SERVER_PORT":             "9090",
+			"GRPC_REGISTRATION_SERVER_URL": "localhost:99999",
+		}
+
+		for key, value := range envVars {
+			assert.NoError(t, os.Setenv(key, value), "Setenv "+key+" should not return an error")
+		}
 
 		config := LoadConfig()
 
-		assert.NoError(t, os.Unsetenv("SERVER_PORT"), "Unsetenv SERVER_PORT should not return an error")
+		for key := range envVars {
+			assert.NoError(t, os.Unsetenv(key), "Unsetenv "+key+" should not return an error")
+		}
 
 		expectedConfig := Config{}
-		expectedConfig.Server.Port = 9090
-		expectedConfig.Grpc.Url = "localhost:50051"
+		expectedConfig.Http.Server.Port = 9090
+		expectedConfig.Grpc.Collaboration.Server.Port = 50052
+		expectedConfig.Grpc.Collaboration.Router.Port = 50051
+		expectedConfig.Grpc.Registration.Server.Url = "localhost:99999"
 		expectedConfig.Grpc.Mock = false
 		expectedConfig.Logging.Level = "DEBUG"
 
diff --git a/internal/config/testdata/test_config.yml b/internal/config/testdata/test_config.yml
index ea8925db9cb5af5c351a1af92d6fb7f878de4359..7cbb36dddca0cc2765c7e42c01a8c268070d8ef8 100644
--- a/internal/config/testdata/test_config.yml
+++ b/internal/config/testdata/test_config.yml
@@ -1,6 +1,14 @@
-server:
-  port: 8080
+http:
+  server:
+    port: 8080
 grpc:
-  url: "localhost:50051"
+  collaboration:
+    server:
+      port: 50052
+    router:
+      port: 50051
+  registration:
+    server:
+      url: "localhost:50052"
 logging:
   level: "DEBUG"
\ No newline at end of file
diff --git a/internal/logging/logger_test.go b/internal/logging/logger_test.go
index 11eff2f85f749fc9bcd884ee9d57c7a9b13fe12d..f0b209ca5d6f61b82ae3e38d3ef1316c8980c1f2 100644
--- a/internal/logging/logger_test.go
+++ b/internal/logging/logger_test.go
@@ -28,21 +28,20 @@ package logging
 import (
 	"bytes"
 	"github.com/stretchr/testify/assert"
-	"log"
 	"testing"
 )
 
-func setUpLogger(t *testing.T, level string, msg string) *bytes.Buffer {
+func logMessage(level string, msg string) *bytes.Buffer {
 	logger := GetLogger()
 
 	var buf bytes.Buffer
 	logger.BaseLogger.SetOutput(&buf)
 
-	originalFlags := log.Flags()
-	t.Cleanup(func() {
-		log.SetOutput(nil)
-		log.SetFlags(originalFlags)
-	})
+	originalFlags := logger.BaseLogger.Flags()
+	defer func() {
+		logger.BaseLogger.SetOutput(nil)
+		logger.BaseLogger.SetFlags(originalFlags)
+	}()
 
 	if level == LogLevelError {
 		logger.Error(msg)
@@ -58,25 +57,25 @@ func setUpLogger(t *testing.T, level string, msg string) *bytes.Buffer {
 }
 
 func TestError(t *testing.T) {
-	buf := setUpLogger(t, LogLevelError, "test error")
-	logOutput := buf.String()
-	assert.Contains(t, logOutput, "ERROR: test error")
+	buf := logMessage(LogLevelError, "test error")
+
+	assert.Contains(t, buf.String(), "ERROR: test error")
 }
 
 func TestWarning(t *testing.T) {
-	buf := setUpLogger(t, LogLevelWarning, "test warning")
-	logOutput := buf.String()
-	assert.Contains(t, logOutput, "WARNING: test warning")
+	buf := logMessage(LogLevelWarning, "test warning")
+
+	assert.Contains(t, buf.String(), "WARNING: test warning")
 }
 
 func TestInfo(t *testing.T) {
-	buf := setUpLogger(t, LogLevelInfo, "test info")
-	logOutput := buf.String()
-	assert.Contains(t, logOutput, "INFO: test info")
+	buf := logMessage(LogLevelInfo, "test info")
+
+	assert.Contains(t, buf.String(), "INFO: test info")
 }
 
 func TestDebug(t *testing.T) {
-	buf := setUpLogger(t, LogLevelDebug, "test debug")
-	logOutput := buf.String()
-	assert.Empty(t, logOutput)
+	buf := logMessage(LogLevelDebug, "test debug")
+
+	assert.Empty(t, buf.String())
 }
diff --git a/internal/logging/testdata/test_config.yml b/internal/logging/testdata/test_config.yml
index 6021893b2e1982f4f8d4215707fa6300e2cd6e8e..64e799f15a52e1afec93177b366e66a3c8c87c88 100644
--- a/internal/logging/testdata/test_config.yml
+++ b/internal/logging/testdata/test_config.yml
@@ -1,6 +1,14 @@
-server:
-  port: 8080
+http:
+  server:
+    port: 8080
 grpc:
-  url: "localhost:50051"
+  collaboration:
+    server:
+      port: 50052
+    router:
+      port: 50051
+  registration:
+    server:
+      url: "localhost:50052"
 logging:
   level: "INFO"
\ No newline at end of file
diff --git a/internal/mock/grpc_server.go b/internal/mock/grpc_server.go
index 729525c994e777903b5877ef109e254031293bcc..bb37e171ab62ffcda7668b16baf5c484d334a8e8 100644
--- a/internal/mock/grpc_server.go
+++ b/internal/mock/grpc_server.go
@@ -32,41 +32,104 @@ import (
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
+	"io"
 	"net"
+	"os"
+	"testing"
 )
 
-const GrpcMockPort = 50051
+const (
+	GrpcMockPort    = 50052
+	defaultFilePath = "internal/mock/testdata/dummy.pdf"
+	testFilePath    = "testdata/dummy.pdf"
+)
 
-type server struct {
+type registrationServer struct {
 	pb.UnimplementedFachstelleRegistrationServiceServer
 }
 
-func (s *server) Register(ctx context.Context, in *pb.GrpcFachstelleRegistrationRequest) (*pb.GrpcFachstelleRegistrationResponse, error) {
+func (s *registrationServer) Register(_ context.Context, in *pb.GrpcFachstelleRegistrationRequest) (*pb.GrpcFachstelleRegistrationResponse, error) {
 	if in.Fachstelle == nil {
-		return nil, status.Error(codes.InvalidArgument, "Fachstelle is missing")
+		return nil, status.Error(codes.InvalidArgument, "fachstelle is missing")
 	}
 
 	if in.Fachstelle.MukId == "conflictMukId" {
-		return nil, status.Error(codes.AlreadyExists, "Conflict mukId")
+		return nil, status.Error(codes.AlreadyExists, "conflict MukId")
 	} else if in.Fachstelle.MukId == "unavailableMukId" {
-		return nil, status.Error(codes.Unavailable, "Unavailable mukId")
+		return nil, status.Error(codes.Unavailable, "unavailable MukId")
 	} else if in.Fachstelle.MukId == "erroneousMukId" {
-		return nil, status.Error(codes.Internal, "Erroneous mukId")
+		return nil, status.Error(codes.Internal, "erroneous MukId")
 	}
 
 	return &pb.GrpcFachstelleRegistrationResponse{}, nil
 }
 
+type collaborationServer struct {
+	pb.UnimplementedCollaborationServiceServer
+}
+
+func (s *collaborationServer) FindVorgang(_ context.Context, in *pb.GrpcFindVorgangRequest) (*pb.GrpcFindVorgangResponse, error) {
+	if in.VorgangId == "" {
+		return nil, status.Error(codes.InvalidArgument, "vorgangId is missing")
+	}
+
+	if in.SamlToken == "" {
+		return nil, status.Error(codes.InvalidArgument, "samlToken is missing")
+	}
+
+	return &pb.GrpcFindVorgangResponse{Vorgang: &pb.GrpcVorgang{Id: "testVorgangId"}}, nil
+}
+
+func (s *collaborationServer) GetFileContent(in *pb.GrpcGetFileContentRequest, stream pb.CollaborationService_GetFileContentServer) error {
+	if in.Id == "" {
+		return status.Error(codes.InvalidArgument, "fileId is missing")
+	}
+
+	if in.SamlToken == "" {
+		return status.Error(codes.InvalidArgument, "samlToken is missing")
+	}
+
+	fp := defaultFilePath
+	if testing.Testing() {
+		fp = testFilePath
+	}
+
+	file, err := os.Open(fp)
+	if err != nil {
+		return err
+	}
+	defer file.Close()
+
+	buffer := make([]byte, 1024*1024)
+	for {
+		bytesRead, err := file.Read(buffer)
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return err
+		}
+
+		chunk := &pb.GrpcGetFileContentResponse{FileContent: buffer[:bytesRead]}
+		if err := stream.Send(chunk); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 func StartGrpcServer() *grpc.Server {
 	s := grpc.NewServer()
-	pb.RegisterFachstelleRegistrationServiceServer(s, &server{})
+	pb.RegisterFachstelleRegistrationServiceServer(s, &registrationServer{})
+	pb.RegisterCollaborationServiceServer(s, &collaborationServer{})
 
 	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", GrpcMockPort))
 	if err != nil {
 		logger.Fatal("gRPC server failed to listen: %v", err)
 	}
 
-	logger.Info("gRPC server listening on port %v", GrpcMockPort)
+	logger.Info("gRPC server listening on port %d", GrpcMockPort)
 	if err := s.Serve(lis); err != nil {
 		logger.Fatal("gRPC server failed to serve: %v", err)
 	}
diff --git a/internal/mock/grpc_server_test.go b/internal/mock/grpc_server_test.go
index b7a4309ea9fb7b52f372928488b849f5c3ef84ca..b9ab84c0db470f438181cb9121cbc8e0340189a4 100644
--- a/internal/mock/grpc_server_test.go
+++ b/internal/mock/grpc_server_test.go
@@ -32,41 +32,103 @@ import (
 	"github.com/stretchr/testify/assert"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials/insecure"
+	"net"
 	"testing"
+	"time"
 )
 
 func TestStartGrpcServer(t *testing.T) {
-	setUpGrpcEnv := func() (pb.FachstelleRegistrationServiceClient, func()) {
+	t.Run("should start gRPC server", func(t *testing.T) {
 		SetUpGrpcServer()
 
-		conn, err := grpc.NewClient(fmt.Sprintf("localhost:%d", GrpcMockPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
+		conn, err := net.DialTimeout("tcp", fmt.Sprintf("localhost:%d", GrpcMockPort), 2*time.Second)
+
 		assert.NoError(t, err)
 
-		cleanup := func() {
-			conn.Close()
+		conn.Close()
+	})
+
+	t.Run("TestFachstelleRegistrationEndpoints", func(t *testing.T) {
+		setUpGrpcEnv := func() (pb.FachstelleRegistrationServiceClient, func()) {
+			SetUpGrpcServer()
+
+			conn, err := grpc.NewClient(fmt.Sprintf("localhost:%d", GrpcMockPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
+			assert.NoError(t, err)
+
+			cleanUp := func() {
+				conn.Close()
+			}
+			client := pb.NewFachstelleRegistrationServiceClient(conn)
+
+			return client, cleanUp
 		}
-		client := pb.NewFachstelleRegistrationServiceClient(conn)
 
-		return client, cleanup
-	}
+		t.Run("should have no error", func(t *testing.T) {
+			client, cleanUp := setUpGrpcEnv()
+			defer cleanUp()
 
-	t.Run("should have no error", func(t *testing.T) {
-		client, cleanUp := setUpGrpcEnv()
-		defer cleanUp()
+			resp, err := client.Register(context.Background(), &pb.GrpcFachstelleRegistrationRequest{Fachstelle: &pb.GrpcFachstelle{MukId: "testMukId"}})
 
-		resp, err := client.Register(context.Background(), &pb.GrpcFachstelleRegistrationRequest{Fachstelle: &pb.GrpcFachstelle{MukId: "testMukId"}})
+			assert.NoError(t, err)
+			assert.NotNil(t, resp)
+		})
 
-		assert.NoError(t, err)
-		assert.NotNil(t, resp)
+		t.Run("should have error", func(t *testing.T) {
+			client, cleanUp := setUpGrpcEnv()
+			defer cleanUp()
+
+			resp, err := client.Register(context.Background(), &pb.GrpcFachstelleRegistrationRequest{})
+
+			assert.Error(t, err)
+			assert.Nil(t, resp)
+		})
 	})
 
-	t.Run("should have error", func(t *testing.T) {
-		client, cleanUp := setUpGrpcEnv()
-		defer cleanUp()
+	t.Run("TestCollaborationEndpoints", func(t *testing.T) {
+		setUpGrpcEnv := func() (pb.CollaborationServiceClient, func()) {
+			SetUpGrpcServer()
+
+			conn, err := grpc.NewClient(fmt.Sprintf("localhost:%d", GrpcMockPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
+			assert.NoError(t, err)
+
+			cleanup := func() {
+				conn.Close()
+			}
+			client := pb.NewCollaborationServiceClient(conn)
+
+			return client, cleanup
+		}
+
+		t.Run("TestFindVorgang", func(t *testing.T) {
+			t.Run("should have no error", func(t *testing.T) {
+				client, cleanUp := setUpGrpcEnv()
+				defer cleanUp()
+
+				resp, err := client.FindVorgang(context.Background(), &pb.GrpcFindVorgangRequest{VorgangId: "testVorgangId", SamlToken: "testSamlToken"})
+
+				assert.NoError(t, err)
+				assert.NotNil(t, resp)
+			})
+
+			t.Run("should have error", func(t *testing.T) {
+				client, cleanUp := setUpGrpcEnv()
+				defer cleanUp()
+
+				resp, err := client.FindVorgang(context.Background(), &pb.GrpcFindVorgangRequest{})
+
+				assert.Error(t, err)
+				assert.Nil(t, resp)
+			})
+		})
+
+		t.Run("TestGetFileContent", func(t *testing.T) {
+			client, cleanUp := setUpGrpcEnv()
+			defer cleanUp()
 
-		resp, err := client.Register(context.Background(), &pb.GrpcFachstelleRegistrationRequest{})
+			resp, err := client.GetFileContent(context.Background(), &pb.GrpcGetFileContentRequest{})
 
-		assert.Error(t, err)
-		assert.Nil(t, resp)
+			assert.NoError(t, err)
+			assert.NotNil(t, resp)
+		})
 	})
 }
diff --git a/internal/mock/testdata/dummy.pdf b/internal/mock/testdata/dummy.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..02dcdbb6d5954ac6019da351a5ad93f191e846aa
Binary files /dev/null and b/internal/mock/testdata/dummy.pdf differ
diff --git a/internal/mock/testdata/test_config.yml b/internal/mock/testdata/test_config.yml
index ea8925db9cb5af5c351a1af92d6fb7f878de4359..7cbb36dddca0cc2765c7e42c01a8c268070d8ef8 100644
--- a/internal/mock/testdata/test_config.yml
+++ b/internal/mock/testdata/test_config.yml
@@ -1,6 +1,14 @@
-server:
-  port: 8080
+http:
+  server:
+    port: 8080
 grpc:
-  url: "localhost:50051"
+  collaboration:
+    server:
+      port: 50052
+    router:
+      port: 50051
+  registration:
+    server:
+      url: "localhost:50052"
 logging:
   level: "DEBUG"
\ No newline at end of file
diff --git a/internal/server/globals.go b/internal/server/globals.go
index 2ac6c4f087be0e6c7ac987c16203e805fe33a552..e0ac55ecc9acee1da4dd01afc4f5bb237bfc3d6d 100644
--- a/internal/server/globals.go
+++ b/internal/server/globals.go
@@ -1,5 +1,14 @@
 package server
 
-import "fachstellen-proxy/internal/logging"
+import (
+	"fachstellen-proxy/internal/config"
+	"fachstellen-proxy/internal/logging"
+)
 
+const (
+	GrpcAddressHeader   = "X-Grpc-Address"
+	GrpcAddressMetadata = "x-grpc-address"
+)
+
+var conf = config.LoadConfig()
 var logger = logging.GetLogger()
diff --git a/internal/server/grpc_router.go b/internal/server/grpc_router.go
new file mode 100644
index 0000000000000000000000000000000000000000..09559ce8ac4226f2e63080d6e03cc9ca3436b1ed
--- /dev/null
+++ b/internal/server/grpc_router.go
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2023-2024
+ * Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+
+package server
+
+import (
+	"context"
+	"errors"
+	pb "fachstellen-proxy/gen/go"
+	"fachstellen-proxy/internal/config"
+	"fachstellen-proxy/internal/mock"
+	"fmt"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/credentials/insecure"
+	"google.golang.org/grpc/metadata"
+	"google.golang.org/grpc/status"
+	"net"
+)
+
+type collaborationRouter struct {
+	pb.UnimplementedCollaborationServiceServer
+}
+
+func (s *collaborationRouter) FindVorgang(ctx context.Context, in *pb.GrpcFindVorgangRequest) (*pb.GrpcFindVorgangResponse, error) {
+	response, err := s.handleRequest(ctx, func(client pb.CollaborationServiceClient, ctx context.Context) (interface{}, error) {
+		return client.FindVorgang(ctx, in)
+	})
+
+	if response == nil {
+		return nil, err
+	}
+
+	return response.(*pb.GrpcFindVorgangResponse), err
+}
+
+func (s *collaborationRouter) handleRequest(ctx context.Context, handler func(pb.CollaborationServiceClient, context.Context) (interface{}, error)) (interface{}, error) {
+	md, ok := metadata.FromIncomingContext(ctx)
+	if !ok {
+		return nil, status.Error(codes.InvalidArgument, "unable to retrieve metadata")
+	}
+
+	grpcAddress := md.Get(GrpcAddressMetadata)
+	if len(grpcAddress) == 0 {
+		return nil, status.Error(codes.InvalidArgument, "grpc address is missing")
+	}
+
+	client, connCleanUp, err := createCollaborationClient(grpcAddress[0])
+	if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+	defer connCleanUp()
+
+	return handler(client, ctx)
+}
+
+func createCollaborationClient(grpcAddress string) (pb.CollaborationServiceClient, func() error, error) {
+	target := GetCollaborationServerUrl(grpcAddress, conf)
+	conn, err := grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		logger.Error("collaboration router failed to route: %v", err)
+
+		return nil, nil, errors.New("collaboration router failed to route")
+	}
+
+	return pb.NewCollaborationServiceClient(conn), conn.Close, nil
+}
+
+func GetCollaborationServerUrl(collaborationServerAddress string, c config.Config) string {
+	collaborationServerPort := c.Grpc.Collaboration.Server.Port
+	if c.Grpc.Mock {
+		collaborationServerPort = mock.GrpcMockPort
+	}
+
+	return fmt.Sprintf("%v:%d", collaborationServerAddress, collaborationServerPort)
+}
+
+func StartCollaborationRouter() *grpc.Server {
+	s := grpc.NewServer()
+	pb.RegisterCollaborationServiceServer(s, &collaborationRouter{})
+
+	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", conf.Grpc.Collaboration.Router.Port))
+	if err != nil {
+		logger.Fatal("collaboration router failed to listen: %v", err)
+	}
+
+	logger.Info("collaboration router listening on port %d", conf.Grpc.Collaboration.Router.Port)
+	if err := s.Serve(lis); err != nil {
+		logger.Fatal("collaboration router failed to serve: %v", err)
+	}
+
+	return s
+}
diff --git a/internal/server/grpc_router_test.go b/internal/server/grpc_router_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..3f5d765d85dd9300fcd1edda59f4a542448ea889
--- /dev/null
+++ b/internal/server/grpc_router_test.go
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2023-2024
+ * Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+
+package server
+
+import (
+	"context"
+	pb "fachstellen-proxy/gen/go"
+	"fachstellen-proxy/internal/config"
+	"fachstellen-proxy/internal/mock"
+	"fmt"
+	"github.com/stretchr/testify/assert"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
+	"google.golang.org/grpc/metadata"
+	"net"
+	"testing"
+	"time"
+)
+
+func TestStartCollaborationRouter(t *testing.T) {
+	setUpGrpcRouterEnv := func() (pb.CollaborationServiceClient, func()) {
+		mock.SetUpGrpcServer()
+		SetUpCollaborationRouter()
+
+		conn, err := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
+		assert.NoError(t, err)
+
+		cleanUp := func() {
+			conn.Close()
+		}
+		client := pb.NewCollaborationServiceClient(conn)
+
+		return client, cleanUp
+	}
+
+	t.Run("should start collaboration router", func(t *testing.T) {
+		SetUpCollaborationRouter()
+
+		conn, err := net.DialTimeout("tcp", "localhost:50051", 2*time.Second)
+
+		assert.NoError(t, err)
+
+		conn.Close()
+	})
+
+	t.Run("should have no error", func(t *testing.T) {
+		client, cleanUp := setUpGrpcRouterEnv()
+		defer cleanUp()
+
+		md := metadata.New(map[string]string{GrpcAddressMetadata: "localhost"})
+		ctx := metadata.NewOutgoingContext(context.Background(), md)
+		resp, err := client.FindVorgang(ctx, &pb.GrpcFindVorgangRequest{VorgangId: "testVorgangId", SamlToken: "testSamlToken"})
+
+		assert.NoError(t, err)
+		assert.NotNil(t, resp)
+	})
+
+	t.Run("should have error", func(t *testing.T) {
+		client, cleanUp := setUpGrpcRouterEnv()
+		defer cleanUp()
+
+		md := metadata.New(map[string]string{GrpcAddressMetadata: "localhost"})
+		ctx := metadata.NewOutgoingContext(context.Background(), md)
+		resp, err := client.FindVorgang(ctx, &pb.GrpcFindVorgangRequest{})
+
+		assert.Error(t, err)
+		assert.Contains(t, err.Error(), "vorgangId is missing")
+		assert.Nil(t, resp)
+	})
+}
+
+func TestGetCollaborationServerUrl(t *testing.T) {
+	t.Run("should have configured server url", func(t *testing.T) {
+		c := config.Config{}
+		c.Grpc.Collaboration.Server.Port = 99999
+
+		result := GetCollaborationServerUrl("localhost", c)
+
+		assert.Equal(t, "localhost:99999", result)
+	})
+
+	t.Run("should have mock server url", func(t *testing.T) {
+		c := config.Config{}
+		c.Grpc.Mock = true
+
+		result := GetCollaborationServerUrl("localhost", c)
+
+		assert.Equal(t, fmt.Sprintf("localhost:%d", mock.GrpcMockPort), result)
+	})
+}
diff --git a/internal/server/handler.go b/internal/server/handler.go
index 3d22eb8fc72bcd32d2e28f676fb07f87aeafdd13..7b024d5b2cf0f44b14e36a1c899c4ffd7aa0cfeb 100644
--- a/internal/server/handler.go
+++ b/internal/server/handler.go
@@ -26,14 +26,25 @@
 package server
 
 import (
+	"bytes"
 	"context"
+	pb "fachstellen-proxy/gen/go"
 	"fmt"
 	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
+	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/credentials/insecure"
 	"google.golang.org/grpc/status"
+	"io"
 	"net/http"
 )
 
+const (
+	fileIdParam          = "id"
+	samlTokenParam       = "samlToken"
+	contentTypeHeaderKey = "Content-Type"
+)
+
 func RegisterHomeEndpoint(mux *runtime.ServeMux) {
 	err := mux.HandlePath("GET", "/", func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
 		defer func() {
@@ -49,6 +60,81 @@ func RegisterHomeEndpoint(mux *runtime.ServeMux) {
 	}
 }
 
+func RegisterFachstelleRegistrationEndpoints(ctx context.Context, mux *runtime.ServeMux, grpcUrl string) {
+	opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
+	err := pb.RegisterFachstelleRegistrationServiceHandlerFromEndpoint(ctx, mux, grpcUrl, opts)
+	if err != nil {
+		logger.Fatal("failed to register fachstelle registration endpoints: %v", err)
+	}
+}
+
+func RegisterCollaborationEndpoints(ctx context.Context, mux *runtime.ServeMux, grpcUrl string) {
+	opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
+	err := pb.RegisterCollaborationServiceHandlerFromEndpoint(ctx, mux, grpcUrl, opts)
+	if err != nil {
+		logger.Fatal("failed to register collaboration endpoints: %v", err)
+	}
+}
+
+func RegisterGetFileEndpoint(mux *runtime.ServeMux) {
+	err := mux.HandlePath("GET", "/api/file/{"+fileIdParam+"}/{"+samlTokenParam+"}", getFileHandler)
+
+	if err != nil {
+		logger.Fatal("failed to register get file endpoint: %v", err)
+	}
+}
+
+func getFileHandler(w http.ResponseWriter, r *http.Request, vars map[string]string) {
+	fileBuffer, err := fetchFileFromGrpc(r.Context(), vars[fileIdParam], vars[samlTokenParam], r.Header.Get(GrpcAddressHeader))
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Set(contentTypeHeaderKey, "application/octet-stream")
+	w.WriteHeader(http.StatusOK)
+
+	_, err = fileBuffer.WriteTo(w)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+}
+
+func fetchFileFromGrpc(ctx context.Context, fileId string, samlToken string, grpcAddress string) (*bytes.Buffer, error) {
+	var fileBuffer bytes.Buffer
+
+	target := GetCollaborationServerUrl(grpcAddress, conf)
+	conn, err := grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		return nil, fmt.Errorf("gRPC connection error")
+	}
+	defer conn.Close()
+
+	client := pb.NewCollaborationServiceClient(conn)
+	req := &pb.GrpcGetFileContentRequest{Id: fileId, SamlToken: samlToken}
+	clientStream, err := client.GetFileContent(ctx, req)
+	if err != nil {
+		return nil, fmt.Errorf("stream creation error")
+	}
+
+	for {
+		resp, err := clientStream.Recv()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return nil, fmt.Errorf("error receiving file chunks")
+		}
+
+		_, err = fileBuffer.Write(resp.FileContent)
+		if err != nil {
+			return nil, fmt.Errorf("error writing file data")
+		}
+	}
+
+	return &fileBuffer, nil
+}
+
 func ErrorHandler(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) {
 	st, ok := status.FromError(err)
 	if !ok {
diff --git a/internal/server/handler_test.go b/internal/server/handler_test.go
index 6cf686e466a16158d655f42a73d99d84f8118564..976134a1502454e94dfcac15caef383b24186d65 100644
--- a/internal/server/handler_test.go
+++ b/internal/server/handler_test.go
@@ -28,7 +28,6 @@ package server
 import (
 	"bytes"
 	"fachstellen-proxy/internal/mock"
-	"fmt"
 	"github.com/stretchr/testify/assert"
 	"net/http"
 	"testing"
@@ -43,12 +42,54 @@ func TestRegisterHomeEndpoint(t *testing.T) {
 	assert.Equal(t, http.StatusOK, resp.StatusCode)
 }
 
+func TestRegisterFachstelleRegistrationEndpoints(t *testing.T) {
+	mock.SetUpGrpcServer()
+	SetUpHttpGateway()
+
+	jsonData := []byte(`{"fachstelle": {"mukId": "testMukId"}}`)
+	resp, err := http.Post("http://localhost:8080/api/fachstellen", "application/json", bytes.NewBuffer(jsonData))
+
+	assert.NoError(t, err)
+	assert.Equal(t, http.StatusOK, resp.StatusCode)
+}
+
+func TestRegisterCollaborationEndpoints(t *testing.T) {
+	mock.SetUpGrpcServer()
+	SetUpCollaborationRouter()
+	SetUpHttpGateway()
+
+	jsonData := []byte(``)
+	req, err := http.NewRequest("GET", "http://localhost:8080/api/vorgang/testVorgangId/testSamlToken", bytes.NewBuffer(jsonData))
+	req.Header.Set(GrpcAddressHeader, "localhost")
+
+	client := &http.Client{}
+	resp, err := client.Do(req)
+
+	assert.NoError(t, err)
+	assert.Equal(t, http.StatusOK, resp.StatusCode)
+}
+
+func TestRegisterGetFileEndpoint(t *testing.T) {
+	mock.SetUpGrpcServer()
+	SetUpHttpGateway()
+
+	jsonData := []byte(``)
+	req, err := http.NewRequest("GET", "http://localhost:8080/api/file/testId/testToken", bytes.NewBuffer(jsonData))
+	req.Header.Set(GrpcAddressHeader, "localhost")
+
+	client := &http.Client{}
+	resp, err := client.Do(req)
+
+	assert.NoError(t, err)
+	assert.Equal(t, http.StatusOK, resp.StatusCode)
+}
+
 func TestErrorHandler(t *testing.T) {
 	assertErroneousRequest := func(jsonData []byte, expectedStatusCode int) {
 		mock.SetUpGrpcServer()
 		SetUpHttpGateway()
 
-		resp, err := http.Post(fmt.Sprintf("http://localhost:8080%v", RegisterFachstelleUrlPath), "application/json", bytes.NewBuffer(jsonData))
+		resp, err := http.Post("http://localhost:8080/api/fachstellen", "application/json", bytes.NewBuffer(jsonData))
 
 		assert.NoError(t, err)
 		assert.Equal(t, expectedStatusCode, resp.StatusCode)
diff --git a/internal/server/http_gateway.go b/internal/server/http_gateway.go
index 5906889cb9e2847e6c6466443fc813ec4adafde7..f3ae00a49b461a9e2c9d46b6be580cb71a0a2978 100644
--- a/internal/server/http_gateway.go
+++ b/internal/server/http_gateway.go
@@ -30,43 +30,48 @@ import (
 	"fachstellen-proxy/internal/config"
 	"fachstellen-proxy/internal/mock"
 	"fmt"
-	"google.golang.org/grpc/credentials/insecure"
+	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
 	"net/http"
+)
 
-	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
-	"google.golang.org/grpc"
+func HeaderMatcher(header string) (string, bool) {
+	if header == GrpcAddressHeader {
+		return header, true
+	}
 
-	pb "fachstellen-proxy/gen/go"
-)
+	return header, false
+}
 
-func StartHttpGateway(conf config.Config) *http.Server {
+func StartHttpGateway() *http.Server {
 	ctx := context.Background()
 	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 
-	grpcEndpoint := conf.Grpc.Url
-	if conf.Grpc.Mock {
-		grpcEndpoint = fmt.Sprintf("localhost:%d", mock.GrpcMockPort)
-	}
-
-	mux := runtime.NewServeMux(runtime.WithErrorHandler(ErrorHandler))
-	opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
-	err := pb.RegisterFachstelleRegistrationServiceHandlerFromEndpoint(ctx, mux, grpcEndpoint, opts)
-	if err != nil {
-		logger.Fatal("failed to start HTTP gateway: %v", err)
-	}
+	mux := runtime.NewServeMux(runtime.WithErrorHandler(ErrorHandler), runtime.WithIncomingHeaderMatcher(HeaderMatcher))
+	collaborationRouterUrl := fmt.Sprintf("localhost:%d", conf.Grpc.Collaboration.Router.Port)
 
 	RegisterHomeEndpoint(mux)
+	RegisterFachstelleRegistrationEndpoints(ctx, mux, GetRegistrationServerUrl(conf))
+	RegisterCollaborationEndpoints(ctx, mux, collaborationRouterUrl)
+	RegisterGetFileEndpoint(mux)
 
 	httpServer := &http.Server{
-		Addr:    fmt.Sprintf(":%d", conf.Server.Port),
+		Addr:    fmt.Sprintf(":%d", conf.Http.Server.Port),
 		Handler: RequestLoggingMiddleware(mux),
 	}
 
-	logger.Info("HTTP gateway listening on port %d", conf.Server.Port)
+	logger.Info("HTTP gateway listening on port %d", conf.Http.Server.Port)
 	if err := httpServer.ListenAndServe(); err != nil {
 		logger.Fatal("HTTP gateway failed to serve: %v", err)
 	}
 
 	return httpServer
 }
+
+func GetRegistrationServerUrl(c config.Config) string {
+	if c.Grpc.Mock {
+		return fmt.Sprintf("localhost:%d", mock.GrpcMockPort)
+	}
+
+	return c.Grpc.Registration.Server.Url
+}
diff --git a/internal/server/http_gateway_test.go b/internal/server/http_gateway_test.go
index 29fcb76ac00bf62862b9090fb20962fdf7abdb6c..7c53380592f678593d2ac4aa7310db0d7568998f 100644
--- a/internal/server/http_gateway_test.go
+++ b/internal/server/http_gateway_test.go
@@ -26,21 +26,55 @@
 package server
 
 import (
-	"bytes"
+	"fachstellen-proxy/internal/config"
 	"fachstellen-proxy/internal/mock"
 	"fmt"
 	"github.com/stretchr/testify/assert"
-	"net/http"
+	"net"
 	"testing"
+	"time"
 )
 
+func TestHeaderMatcher(t *testing.T) {
+	t.Run("should accept header", func(t *testing.T) {
+		_, accepted := HeaderMatcher(GrpcAddressHeader)
+
+		assert.True(t, accepted)
+	})
+
+	t.Run("should reject header", func(t *testing.T) {
+		_, accepted := HeaderMatcher("X-Rejected-Header")
+
+		assert.False(t, accepted)
+	})
+}
+
 func TestStartHttpGateway(t *testing.T) {
-	mock.SetUpGrpcServer()
 	SetUpHttpGateway()
 
-	jsonData := []byte(`{"fachstelle": {"mukId": "testMukId"}}`)
-	resp, err := http.Post(fmt.Sprintf("http://localhost:8080%v", RegisterFachstelleUrlPath), "application/json", bytes.NewBuffer(jsonData))
+	conn, err := net.DialTimeout("tcp", "localhost:8080", 2*time.Second)
 
 	assert.NoError(t, err)
-	assert.Equal(t, http.StatusOK, resp.StatusCode)
+
+	conn.Close()
+}
+
+func TestGetRegistrationServerUrl(t *testing.T) {
+	t.Run("should have configured server url", func(t *testing.T) {
+		c := config.Config{}
+		c.Grpc.Registration.Server.Url = "localhost:99999"
+
+		result := GetRegistrationServerUrl(c)
+
+		assert.Equal(t, "localhost:99999", result)
+	})
+
+	t.Run("should have mock server url", func(t *testing.T) {
+		c := config.Config{}
+		c.Grpc.Mock = true
+
+		result := GetRegistrationServerUrl(c)
+
+		assert.Equal(t, fmt.Sprintf("localhost:%d", mock.GrpcMockPort), result)
+	})
 }
diff --git a/internal/server/middleware.go b/internal/server/middleware.go
index fdab80b369121d04af22fe2cc6a0f2dd85a01b34..41710750de6006fed161507fd8ba65846ef1601b 100644
--- a/internal/server/middleware.go
+++ b/internal/server/middleware.go
@@ -32,7 +32,7 @@ import (
 	"net/http"
 )
 
-const RegisterFachstelleUrlPath = "/api/fachstellen"
+const HomeUrlPath = "/"
 
 type logResponseWriter struct {
 	http.ResponseWriter
@@ -46,28 +46,28 @@ func (rsp *logResponseWriter) WriteHeader(statusCode int) {
 
 func RequestLoggingMiddleware(h http.Handler) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		if r.URL.Path != RegisterFachstelleUrlPath {
+		if r.URL.Path == HomeUrlPath {
 			h.ServeHTTP(w, r)
 			return
 		}
 
 		body, err := io.ReadAll(r.Body)
 		if err != nil {
-			logger.Error("failed to read request body: %v", err)
+			logger.Error("failed to read %v request body for %v: %v", r.Method, r.URL.Path, err)
 			http.Error(w, fmt.Sprintf("failed to read request body: %v", err), http.StatusBadRequest)
 			return
 		}
 		r.Body = io.NopCloser(bytes.NewReader(body))
 
-		logger.Debug("received request with body: %v", string(body))
+		logger.Debug("received %v request for %v with body: %v", r.Method, r.URL.Path, string(body))
 
 		lw := &logResponseWriter{w, http.StatusOK}
 		h.ServeHTTP(lw, r)
 
 		if lw.statusCode == http.StatusOK {
-			logger.Debug("successfully handled request with body: %v", string(body))
+			logger.Debug("successfully handled %v request for %v with body: %v", r.Method, r.URL.Path, string(body))
 		} else {
-			logger.Error("failed handling request with body: %v, status code: %d", string(body), lw.statusCode)
+			logger.Error("failed handling %v request for %v with body: %v, status code: %d", r.Method, r.URL.Path, string(body), lw.statusCode)
 		}
 	})
 }
diff --git a/internal/server/middleware_test.go b/internal/server/middleware_test.go
index b69bed46805ec058e48d8b01d33b0f50eb075901..90806e9ca0b4077e8383c3f1cb089f7fdfd0f70e 100644
--- a/internal/server/middleware_test.go
+++ b/internal/server/middleware_test.go
@@ -28,30 +28,49 @@ package server
 import (
 	"bytes"
 	"fachstellen-proxy/internal/mock"
-	"fmt"
 	"github.com/stretchr/testify/assert"
-	"log"
 	"net/http"
 	"testing"
 )
 
 func TestRequestLoggingMiddleware(t *testing.T) {
-	mock.SetUpGrpcServer()
-	SetUpHttpGateway()
+	t.Run("should log request", func(t *testing.T) {
+		mock.SetUpGrpcServer()
+		SetUpHttpGateway()
 
-	var buf bytes.Buffer
-	logger.BaseLogger.SetOutput(&buf)
+		var buf bytes.Buffer
+		logger.BaseLogger.SetOutput(&buf)
 
-	originalFlags := log.Flags()
-	defer func() {
-		log.SetOutput(nil)
-		log.SetFlags(originalFlags)
-	}()
+		originalFlags := logger.BaseLogger.Flags()
+		defer func() {
+			logger.BaseLogger.SetOutput(nil)
+			logger.BaseLogger.SetFlags(originalFlags)
+		}()
 
-	jsonData := []byte(`{"fachstelle": {"mukId": "testMukId"}}`)
-	http.Post(fmt.Sprintf("http://localhost:8080%v", RegisterFachstelleUrlPath), "application/json", bytes.NewBuffer(jsonData))
+		jsonData := []byte(`{"fachstelle": {"mukId": "testMukId"}}`)
+		http.Post("http://localhost:8080/api/fachstellen", "application/json", bytes.NewBuffer(jsonData))
 
-	logOutput := buf.String()
-	assert.Contains(t, logOutput, "received request with body: {\"fachstelle\": {\"mukId\": \"testMukId\"}}")
-	assert.Contains(t, logOutput, "successfully handled request with body: {\"fachstelle\": {\"mukId\": \"testMukId\"}}")
+		logOutput := buf.String()
+		assert.Contains(t, logOutput, "received POST request for /api/fachstellen with body: {\"fachstelle\": {\"mukId\": \"testMukId\"}}")
+		assert.Contains(t, logOutput, "successfully handled POST request for /api/fachstellen with body: {\"fachstelle\": {\"mukId\": \"testMukId\"}}")
+	})
+
+	t.Run("should not log request", func(t *testing.T) {
+		mock.SetUpGrpcServer()
+		SetUpHttpGateway()
+
+		var buf bytes.Buffer
+		logger.BaseLogger.SetOutput(&buf)
+
+		originalFlags := logger.BaseLogger.Flags()
+		defer func() {
+			logger.BaseLogger.SetOutput(nil)
+			logger.BaseLogger.SetFlags(originalFlags)
+		}()
+
+		http.Get("http://localhost:8080/")
+
+		logOutput := buf.String()
+		assert.Empty(t, logOutput)
+	})
 }
diff --git a/internal/server/test_setup.go b/internal/server/test_setup.go
index 5c3fd654df03385a9d008e716c93c7a60843b6cf..80bf7b2ea62875de84469231a028aa966cc0b1ab 100644
--- a/internal/server/test_setup.go
+++ b/internal/server/test_setup.go
@@ -26,18 +26,23 @@
 package server
 
 import (
-	"fachstellen-proxy/internal/config"
 	"sync"
 	"time"
 )
 
-var setUpOnce sync.Once
+var setUpHttpGatewayOnce sync.Once
+var setUpCollaborationRouterOnce sync.Once
 
 func SetUpHttpGateway() {
-	setUpOnce.Do(func() {
-		conf := config.LoadConfig()
-
-		go StartHttpGateway(conf)
+	setUpHttpGatewayOnce.Do(func() {
+		go StartHttpGateway()
 		time.Sleep(time.Second) // Wait for the server to start
 	})
 }
+
+func SetUpCollaborationRouter() {
+	setUpCollaborationRouterOnce.Do(func() {
+		go StartCollaborationRouter()
+		time.Sleep(time.Second) // Wait for the router to start
+	})
+}
diff --git a/internal/server/testdata/dummy.pdf b/internal/server/testdata/dummy.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..02dcdbb6d5954ac6019da351a5ad93f191e846aa
Binary files /dev/null and b/internal/server/testdata/dummy.pdf differ
diff --git a/internal/server/testdata/test_config.yml b/internal/server/testdata/test_config.yml
index 6235966c8828f67d39820aeb96b70781ca9300f7..c18dc59a3584edbc4f5b1bfdb480c716d78bf866 100644
--- a/internal/server/testdata/test_config.yml
+++ b/internal/server/testdata/test_config.yml
@@ -1,6 +1,10 @@
-server:
-  port: 8080
+http:
+  server:
+    port: 8080
 grpc:
+  collaboration:
+    router:
+      port: 50051
   mock: true
 logging:
   level: "DEBUG"
\ No newline at end of file
diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
index ffcc3c8e6d1ec47d533e67f9abd17aab29c03fb2..cb1dc50237f22fdfcce25f2b96c09c124e28c9d5 100644
--- a/src/main/helm/templates/deployment.yaml
+++ b/src/main/helm/templates/deployment.yaml
@@ -58,12 +58,14 @@ spec:
             app.kubernetes.io/name: {{ .Release.Name }}
       containers:
       - env:
-          - name: SERVER_PORT
+          - name: HTTP_SERVER_PORT
             value: "8082"
           - name: GRPC_MOCK
             value: "{{ (.Values.grpc).mock | default false }}"
-          - name: GRPC_URL
-            value: "{{ required ".Values.grpc.url must be set" (.Values.grpc).url }}"
+          - name: GRPC_REGISTRATION_SERVER_URL
+            value: "{{ required ".Values.grpc.registration.server.url must be set" (((.Values.grpc).registration).server).url }}"
+          - name: GRPC_COLLABORATION_SERVER_PORT
+            value: "9090"
           {{- with include "app.getCustomList" . }}
 {{ . | indent 10 }}
           {{- end }}
diff --git a/src/test/helm-linter-values.yaml b/src/test/helm-linter-values.yaml
index bab44e4f88591b71dd0cb0220909949f70cfc0e4..2e0237dfb94f4f00c52bfa9693470b69367f4eb9 100644
--- a/src/test/helm-linter-values.yaml
+++ b/src/test/helm-linter-values.yaml
@@ -1,14 +1,38 @@
-
+#
+# 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.
+#
 
 networkPolicy:
   dnsServerNamespace: test-dns-namespace
 
-
 zufiManager:
   namespace: zufi
 
 imagePullSecret: ozgcloud-image-pull-secret
-server:
-  port: 8080
+http:
+  server:
+    port: 8080
 grpc:
-  url: "zufi.de:9090"
\ No newline at end of file
+  registration:
+    server:
+      url: "zufi.de:9090"
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_labels_test.yaml b/src/test/helm/deployment_defaults_labels_test.yaml
index 3b2ddae990c85307b257db1c6aef07da97991bdc..18ddbba77713c96f84851e3bda4e398e8d474fd5 100644
--- a/src/test/helm/deployment_defaults_labels_test.yaml
+++ b/src/test/helm/deployment_defaults_labels_test.yaml
@@ -30,10 +30,18 @@ templates:
   - templates/deployment.yaml
 set:
   imagePullSecret: image-pull-secret
-  server:
-    port: 8080
+  http:
+    server:
+      port: 8080
   grpc:
-    url: "zufi.de:9090"
+    collaboration:
+      router:
+        port: 50051
+      server:
+        port: 50052
+    registration:
+      server:
+        url: "zufi.de:9090"
 tests:
   - it: check metadata.labels
     asserts:
diff --git a/src/test/helm/deployment_env_test.yaml b/src/test/helm/deployment_env_test.yaml
index 291459906207c5e4cceb50f29962d43e5e58ed6c..19ea5ae90e4e905fa3162534a29291c4663cc484 100644
--- a/src/test/helm/deployment_env_test.yaml
+++ b/src/test/helm/deployment_env_test.yaml
@@ -36,7 +36,9 @@ tests:
         - name: test_environment
           value: "B test value"
       grpc:
-        url: "zufi.de:9090"
+        registration:
+          server:
+            url: "zufi.de:9090"
     asserts:
       - contains:
           path: spec.template.spec.containers[0].env
@@ -54,7 +56,9 @@ tests:
         my_test_environment_name: "A test value"
         test_environment: "B test value"
       grpc:
-        url: "zufi.de:9090"
+        registration:
+          server:
+            url: "zufi.de:9090"
     asserts:
       - contains:
           path: spec.template.spec.containers[0].env
@@ -70,12 +74,19 @@ tests:
   - it: check envs
     set:       
       grpc:
-        url: "zufi.de:9090"
+        registration:
+          server:
+            url: "zufi.de:9090"
     asserts:
       - contains:
           path: spec.template.spec.containers[0].env
           content:
-            name: GRPC_URL
+            name: GRPC_COLLABORATION_SERVER_PORT
+            value: "9090"
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: GRPC_REGISTRATION_SERVER_URL
             value: "zufi.de:9090"
       - contains:
           path: spec.template.spec.containers[0].env
@@ -85,10 +96,10 @@ tests:
       - contains:
           path: spec.template.spec.containers[0].env
           content:
-            name: SERVER_PORT
+            name: HTTP_SERVER_PORT
             value: "8082"
-  - it: should fail template if grpc.url not set
+  - it: should fail template if grpc.registration.server.url not set
     set:
     asserts:
       - failedTemplate:
-          errormessage: ".Values.grpc.url must be set"
\ No newline at end of file
+          errormessage: ".Values.grpc.registration.server.url must be set"
diff --git a/src/test/helm/deployment_imagepull_secret_test.yaml b/src/test/helm/deployment_imagepull_secret_test.yaml
index bbfb1b1f114d95e7e87e1b6e16e0e1fc31e85090..6e3d7f932494d6185a8bb9bb49677ca9cb923b3c 100644
--- a/src/test/helm/deployment_imagepull_secret_test.yaml
+++ b/src/test/helm/deployment_imagepull_secret_test.yaml
@@ -29,10 +29,18 @@ release:
 templates:
   - templates/deployment.yaml
 set:
-  server:
-    port: 8080
+  http:
+    server:
+      port: 8080
   grpc:
-    url: "zufi.de:9090"
+    collaboration:
+      router:
+        port: 50051
+      server:
+        port: 50052
+    registration:
+      server:
+        url: "zufi.de:9090"
 tests:
   - it: should use correct imagePull secret
     set: 
diff --git a/src/test/helm/deployment_resources_test.yaml b/src/test/helm/deployment_resources_test.yaml
index c88ff160680f16afdfb2e8e7fd3cf639303fbc5e..5af9adb1d4d1473267eab1679bfe07af0de714f9 100644
--- a/src/test/helm/deployment_resources_test.yaml
+++ b/src/test/helm/deployment_resources_test.yaml
@@ -29,10 +29,18 @@ templates:
   - templates/deployment.yaml
 set:
   imagePullSecret: image-pull-secret
-  server:
-    port: 8080
+  http:
+    server:
+      port: 8080
   grpc:
-    url: "zufi.de:9090"
+    collaboration:
+      router:
+        port: 50051
+      server:
+        port: 50052
+    registration:
+      server:
+        url: "zufi.de:9090"
 
 tests:
   - it: should generate resources when values set
diff --git a/src/test/helm/deployment_test.yaml b/src/test/helm/deployment_test.yaml
index b4b72cdd3745818b41046a4035795d050a9a2a7e..c04f82edfedb732187e220f54b3145bd0c971db9 100644
--- a/src/test/helm/deployment_test.yaml
+++ b/src/test/helm/deployment_test.yaml
@@ -29,10 +29,18 @@ templates:
   - templates/deployment.yaml
 set:
   imagePullSecret: image-pull-secret
-  server:
-    port: 8080
+  http:
+    server:
+      port: 8080
   grpc:
-    url: "zufi.de:9090"
+    collaboration:
+      router:
+        port: 50051
+      server:
+        port: 50052
+    registration:
+      server:
+        url: "zufi.de:9090"
 
 tests:
   - it: should have metadata values