diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileDownloadStreamObserver.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileDownloadStreamObserver.java
deleted file mode 100644
index 368563ae5f200722690525324ada3383c33ae4c8..0000000000000000000000000000000000000000
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileDownloadStreamObserver.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2023-2024.
- * 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.antragsraum.attachments;
-
-import de.ozgcloud.antragsraum.common.TechnicalException;
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
-import io.grpc.stub.StreamObserver;
-import lombok.AccessLevel;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.log4j.Log4j2;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.concurrent.CompletableFuture;
-
-@Log4j2
-@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
-class FileDownloadStreamObserver implements StreamObserver<GrpcGetBinaryFileDataResponse> {
-	private final CompletableFuture<Boolean> streamFuture;
-	private final OutputStream out;
-
-	@Override
-	public void onNext(GrpcGetBinaryFileDataResponse response) {
-		writeToStream(response.getFileContent().toByteArray());
-	}
-
-	void writeToStream(byte[] contentPart) {
-		try {
-			out.write(contentPart);
-		} catch (IOException e) {
-			LOG.error("Download file error writing on output stream", e);
-			throw new TechnicalException(e);
-		}
-	}
-
-	@Override
-	public void onError(Throwable t) {
-		streamFuture.completeExceptionally(t);
-	}
-
-	@Override
-	public void onCompleted() {
-		streamFuture.complete(true);
-	}
-}
diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileGrpcClient.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileGrpcClient.java
deleted file mode 100644
index c6b455095a4f44465240c30648c376df66168b71..0000000000000000000000000000000000000000
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileGrpcClient.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2023-2024.
- * 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.antragsraum.attachments;
-
-import java.io.OutputStream;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.springframework.stereotype.Component;
-
-import com.google.protobuf.ByteString;
-
-import de.ozgcloud.antragsraum.callcontext.ContextService;
-import de.ozgcloud.antragsraum.common.TechnicalException;
-import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc;
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcBinaryFilesRequest;
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcFindFilesResponse;
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileMetaData;
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import io.grpc.stub.StreamObserver;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-
-@Component
-@RequiredArgsConstructor
-class FileGrpcClient {
-	public static final int CHUNK_SIZE = 255 * 1024;
-
-	private final @NonNull ContextService contextService;
-
-	GrpcFindFilesResponse findBinaryFilesMetaData(GrpcBinaryFilesRequest request, String address) {
-		/*try (GrpcChannelFactory channelFactory = getChannelFactory(address)) {
-			var channel = channelFactory.createChannel(address);
-			var serviceStub = BinaryFileServiceGrpc.newBlockingStub(channel);
-
-			return getBinaryFilesMetaData(request, serviceStub);
-		}*/
-
-		return null;
-	}
-
-	GrpcFindFilesResponse getBinaryFilesMetaData(GrpcBinaryFilesRequest request,
-	  BinaryFileServiceGrpc.BinaryFileServiceBlockingStub fileServiceBlockingStub) {
-		return fileServiceBlockingStub.findBinaryFilesMetaData(request);
-	}
-
-	StreamObserver<GrpcUploadBinaryFileRequest> uploadFile(OzgUploadFile uploadFile, String address, CompletableFuture<String> fileIdFuture) {
-		/*try (GrpcChannelFactory channelFactory = getChannelFactory(address)) {
-			var channel = channelFactory.createChannel(address);
-			var responseObserver = createUploadFileObserver(fileIdFuture, uploadFile);
-			var serviceStub = BinaryFileServiceGrpc.newStub(channel);
-
-			return doUploadFiles(responseObserver, serviceStub);
-		}*/
-
-		return null;
-	}
-
-	StreamObserver<GrpcUploadBinaryFileRequest> doUploadFiles(FileUploadStreamObserver observer,
-	  BinaryFileServiceGrpc.BinaryFileServiceStub asyncServiceStub) {
-		return asyncServiceStub.uploadBinaryFileAsStream(observer);
-	}
-
-	FileUploadStreamObserver createUploadFileObserver(CompletableFuture<String> fileIdFuture, OzgUploadFile uploadFile) {
-		var metadataRequest = buildMetaDataRequest(uploadFile);
-		var streamer = new ChunkedFileSender<>(uploadFile.fileContent(), CHUNK_SIZE, this::buildChunkRequest, metadataRequest);
-		return new FileUploadStreamObserver(fileIdFuture, streamer);
-	}
-
-	private GrpcUploadBinaryFileRequest buildMetaDataRequest(OzgUploadFile uploadFile) {
-		return GrpcUploadBinaryFileRequest.newBuilder()
-		  .setMetadata(GrpcUploadBinaryFileMetaData.newBuilder()
-			.setContext(contextService.createCallContext())
-			.setVorgangId(uploadFile.fileData().getVorgangId())
-			.setContentType(uploadFile.fileData().getContentType())
-			.setFileName(uploadFile.fileData().getFileName()))
-		  .build();
-	}
-
-	GrpcUploadBinaryFileRequest buildChunkRequest(byte[] bytes) {
-		return GrpcUploadBinaryFileRequest.newBuilder().setFileContent((ByteString.copyFrom(bytes))).build();
-	}
-
-	void downloadFileContent(String fileId, OutputStream out, String address) {
-		/*try (GrpcChannelFactory channelFactory = getChannelFactory(address)) {
-			var channel = channelFactory.createChannel(address);
-			var serviceStub = BinaryFileServiceGrpc.newStub(channel);
-
-			doDownloadFileContent(fileId, out, serviceStub);
-		}*/
-	}
-
-	void doDownloadFileContent(String fileId, OutputStream out, BinaryFileServiceGrpc.BinaryFileServiceStub binaryFileServiceStub) {
-		var streamFuture = new CompletableFuture<Boolean>();
-		var responseObserver = createDownloadFileObserver(streamFuture, out);
-		binaryFileServiceStub.getBinaryFileContent(buildGrpcGetBinaryFileDataRequest(fileId), responseObserver);
-
-		waitUntilFutureToComplete(streamFuture);
-
-	}
-
-	FileDownloadStreamObserver createDownloadFileObserver(CompletableFuture<Boolean> streamFuture, OutputStream out) {
-		return new FileDownloadStreamObserver(streamFuture, out);
-	}
-
-	private GrpcGetBinaryFileDataRequest buildGrpcGetBinaryFileDataRequest(String fileId) {
-		return GrpcGetBinaryFileDataRequest.newBuilder().setFileId(fileId).build();
-	}
-
-	void waitUntilFutureToComplete(CompletableFuture<Boolean> streamFuture) {
-		try {
-			streamFuture.get(10, TimeUnit.MINUTES);
-		} catch (InterruptedException e) {
-			Thread.currentThread().interrupt();
-			throw new TechnicalException(e);
-		} catch (ExecutionException | TimeoutException e) {
-			throw new TechnicalException(e);
-		}
-	}
-}
\ No newline at end of file
diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRemoteService.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRemoteService.java
index cb2d5b0a17d2d366c29f466bec5777262b170e9e..bc0972de004cb834f28abcf52bb107459719e572 100644
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRemoteService.java
+++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRemoteService.java
@@ -20,12 +20,13 @@
 
 package de.ozgcloud.antragsraum.attachments;
 
+import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 
 import org.springframework.stereotype.Service;
 
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcBinaryFilesRequest;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
@@ -34,13 +35,18 @@ import lombok.extern.log4j.Log4j2;
 @Service
 @RequiredArgsConstructor
 class FileRemoteService {
-	private final @NonNull FileGrpcClient grpcClient;
+	private final @NonNull FileRestClient restClient;
 
 	OzgFile getFile(String fileId, String address) {
-		var grpcFileMetadata = grpcClient.findBinaryFilesMetaData(buildGrpcBinaryFileRequest(fileId), address);
+		var grpcFileMetadata = restClient.findBinaryFilesMetaData(fileId, address);
 
-		if (!grpcFileMetadata.getFileList().isEmpty()) {
-			return OzgFileMapper.fromGrpcFile(grpcFileMetadata.getFile(0));
+		if (Objects.isNull(grpcFileMetadata.getFile())) {
+			LOG.warn("Received file id {} from {}, but findBinaryFilesMetaData returned empty file list", fileId, address);
+			return null;
+		}
+
+		if (!grpcFileMetadata.getFile().isEmpty()) {
+			return OzgFileMapper.fromRestFile(grpcFileMetadata.getFile().getFirst());
 		}
 
 		LOG.warn("Received file id {} from {}, but findBinaryFilesMetaData returned empty file list", fileId, address);
@@ -48,21 +54,18 @@ class FileRemoteService {
 		return null;
 	}
 
-	private GrpcBinaryFilesRequest buildGrpcBinaryFileRequest(String fileId) {
-		return GrpcBinaryFilesRequest.newBuilder()
-		  .addFileId(fileId)
-		  .build();
-	}
-
 	CompletableFuture<String> uploadFile(OzgUploadFile uploadFile, String address) {
 		var fileIdFuture = new CompletableFuture<String>();
-		var request = grpcClient.uploadFile(uploadFile, address, fileIdFuture);
-		LOG.debug("Grpc File Upload Request: {}", request);
+		restClient.uploadFile(uploadFile, address, fileIdFuture);
 
 		return fileIdFuture;
 	}
 
 	void downloadFileContent(String fileId, OutputStream out, String address) {
-		grpcClient.downloadFileContent(fileId, out, address);
+		try {
+			restClient.downloadFileContent(fileId, out, address);
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
 	}
 }
diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRestClient.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRestClient.java
index 3969b6b415027eda8382accb7a61d03ebd12458c..09a71960bc56a9171d8e1b3d9afb9430886c106f 100644
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRestClient.java
+++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRestClient.java
@@ -22,15 +22,98 @@
 
 package de.ozgcloud.antragsraum.attachments;
 
+import static de.ozgcloud.antragsraum.WebConfiguration.*;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.core.io.Resource;
+import org.springframework.http.MediaType;
 import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestClient;
 
 import de.ozgcloud.antragsraum.callcontext.ContextService;
+import de.ozgcloud.antragsraum.common.RestClientUtils;
+import de.ozgcloud.antragsraum.common.TechnicalException;
+import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcFindFilesResponse;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
 
+@Log4j2
 @Component
 @RequiredArgsConstructor
 public class FileRestClient {
-	public static final int CHUNK_SIZE = 255 * 1024;
+	private static final String FIND_FILE_METADATA_API = "/api/v1/file/metadata/{fileId}";
+	private static final String GET_FILE_CONTENT_API = "/api/v1/file/content/{fileId}";
+	static final String UPLOAD_FILE_API = "/api/v1/file";
 	private final @NonNull ContextService contextService;
+	private final @NonNull RestClient nachrichtRestClient;
+
+	public AntragraumproxyGrpcFindFilesResponse findBinaryFilesMetaData(String fileId, final String address) {
+		return nachrichtRestClient
+		  .get()
+		  .uri(FIND_FILE_METADATA_API, fileId)
+		  .accept(MediaType.APPLICATION_JSON)
+		  .header(X_GRPC_ADDRESS, RestClientUtils.sanitizeAddress(address))
+		  .retrieve()
+		  .toEntity(AntragraumproxyGrpcFindFilesResponse.class).getBody();
+	}
+
+	public void uploadFile(final OzgUploadFile uploadFile, final String address, final CompletableFuture<String> fileIdFuture) {
+		try {
+			var response = sendFile(uploadFile, address);
+			if (Objects.nonNull(response)) {
+				fileIdFuture.complete(response);
+			} else {
+				fileIdFuture.completeExceptionally(new IllegalStateException("No fileId received"));
+			}
+		} catch (Exception e) {
+			fileIdFuture.completeExceptionally(e);
+		}
+	}
+
+	private String sendFile(OzgUploadFile uploadFile, String address) {
+
+		MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
+		requestBody.add("file", uploadFile.file().getResource());
+		requestBody.add("vorgangId", uploadFile.vorgangId());
+
+		var fileId = nachrichtRestClient
+		  .post()
+		  .uri(UPLOAD_FILE_API)
+		  .header(X_GRPC_ADDRESS, RestClientUtils.sanitizeAddress(address))
+		  .contentType(MediaType.MULTIPART_FORM_DATA)
+		  .body(requestBody)
+		  .retrieve().toEntity(String.class).getBody();
+		LOG.info("received {}", fileId);
+
+		return fileId;
+	}
+
+	public void downloadFileContent(final String fileId, final OutputStream out, final String address) throws IOException {
+		var fileContent = Optional.ofNullable(nachrichtRestClient
+		  .get()
+		  .uri(GET_FILE_CONTENT_API, fileId)
+		  .header(X_GRPC_ADDRESS, RestClientUtils.sanitizeAddress(address))
+		  .accept(MediaType.APPLICATION_OCTET_STREAM)
+		  .retrieve().toEntity(Resource.class).getBody());
+
+		fileContent.ifPresent(file -> processFile(out, file));
+	}
+
+	private static void processFile(final OutputStream out, Resource fileContent) {
+		try {
+			IOUtils.copy(fileContent.getInputStream(), out);
+		} catch (IOException e) {
+			LOG.error("Error writing file content to output", e);
+			throw new TechnicalException(e);
+		}
+	}
 }
diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileService.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileService.java
index 56b6e2d270cee833ebee006176f11f9c09b3a456..99041ce9e5862efcd444b2baf613fcc1949f4886 100644
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileService.java
+++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileService.java
@@ -20,18 +20,14 @@
 
 package de.ozgcloud.antragsraum.attachments;
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.concurrent.CompletableFuture;
 
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
-import de.ozgcloud.antragsraum.common.TechnicalException;
 import de.ozgcloud.antragsraum.common.VirusFoundException;
 import de.ozgcloud.antragsraum.events.NachrichtEventService;
-import de.ozgcloud.apilib.file.OzgCloudUploadFile;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
@@ -67,12 +63,8 @@ public class FileService {
 			LOG.info("File {} is clean, preparing upload", file.getOriginalFilename());
 
 			return OzgUploadFile.builder()
-			  .fileData(OzgCloudUploadFile.builder()
-				.fileName(file.getOriginalFilename())
-				.contentType(file.getContentType())
-				.vorgangId(vorgangId)
-				.build())
-			  .fileContent(getInputStream(file))
+			  .vorgangId(vorgangId)
+			  .file(file)
 			  .build();
 		}
 
@@ -83,13 +75,4 @@ public class FileService {
 	boolean isClean(MultipartFile file) {
 		return scanner.scan(file).isEmpty();
 	}
-
-	private InputStream getInputStream(MultipartFile file) {
-		try {
-			return file.getInputStream();
-		} catch (IOException e) {
-			LOG.error("Error reading file data as stream.", e);
-			throw new TechnicalException(e);
-		}
-	}
 }
diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileUploadStreamObserver.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileUploadStreamObserver.java
deleted file mode 100644
index 534fd691d3c60241e9dcffcd9dba4c8a9f9b7ae3..0000000000000000000000000000000000000000
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileUploadStreamObserver.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2023-2024.
- * 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.antragsraum.attachments;
-
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileResponse;
-import io.grpc.stub.ClientCallStreamObserver;
-import io.grpc.stub.ClientResponseObserver;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import java.util.concurrent.CompletableFuture;
-
-@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
-class FileUploadStreamObserver implements ClientResponseObserver<GrpcUploadBinaryFileRequest, GrpcUploadBinaryFileResponse> {
-    private final CompletableFuture<String> fileIdFuture;
-    private final ChunkedFileSender<GrpcUploadBinaryFileRequest> fileStreamer;
-
-    @Getter
-    private String fileId;
-
-    private ClientCallStreamObserver<GrpcUploadBinaryFileRequest> requestObserver;
-
-    @Override
-    public void beforeStart(ClientCallStreamObserver<GrpcUploadBinaryFileRequest> requestStream) {
-        this.requestObserver = requestStream;
-        requestObserver.setOnReadyHandler(() -> fileStreamer.sendChunkTo(requestObserver));
-    }
-
-    @Override
-    public void onNext(GrpcUploadBinaryFileResponse response) {
-        fileId = response.getFileId();
-    }
-
-    @Override
-    public void onError(Throwable t) {
-        fileIdFuture.completeExceptionally(t);
-    }
-
-    @Override
-    public void onCompleted() {
-        fileIdFuture.complete(fileId);
-    }
-}
diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgFileMapper.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgFileMapper.java
index 8ff6526dacc8a1f43b27d6fef0b240759766305c..885f8d8d1aa6a9a2b3bdc69d3925983053eb6b02 100644
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgFileMapper.java
+++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgFileMapper.java
@@ -20,19 +20,33 @@
 
 package de.ozgcloud.antragsraum.attachments;
 
-import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
+import java.util.Objects;
+
+import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcOzgFile;
+import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcUploadBinaryFileMetaData;
+import de.ozgcloud.apilib.file.OzgCloudUploadFile;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 class OzgFileMapper {
 
-	static OzgFile fromGrpcFile(GrpcOzgFile grpcFile) {
+	static OzgFile fromRestFile(AntragraumproxyGrpcOzgFile grpcFile) {
 		return OzgFile.builder()
 		  .id(grpcFile.getId())
 		  .fileName(grpcFile.getName())
 		  .contentType(grpcFile.getContentType())
-		  .fileSize(grpcFile.getSize())
+		  .fileSize(Objects.nonNull(grpcFile.getSize()) ? Long.parseLong(grpcFile.getSize()) : -1L)
 		  .build();
 	}
+
+	static AntragraumproxyGrpcUploadBinaryFileMetaData toGrpcUploadBinaryFileMetaData(OzgCloudUploadFile ozgFile) {
+		var metaData = new AntragraumproxyGrpcUploadBinaryFileMetaData();
+		metaData.contentType(ozgFile.getContentType());
+		metaData.setFileName(ozgFile.getFileName());
+		metaData.setVorgangId(ozgFile.getVorgangId());
+		metaData.setField(ozgFile.getFieldName());
+
+		return metaData;
+	}
 }
diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgUploadFile.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgUploadFile.java
index 67060e8ca477c699f35f85f33f20039b8536e34b..e716d36724a3725f1e0af677a4ab6573972c3757 100644
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgUploadFile.java
+++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgUploadFile.java
@@ -20,14 +20,12 @@
 
 package de.ozgcloud.antragsraum.attachments;
 
-import java.io.InputStream;
-
 import org.springframework.validation.annotation.Validated;
+import org.springframework.web.multipart.MultipartFile;
 
-import de.ozgcloud.apilib.file.OzgCloudUploadFile;
 import lombok.Builder;
 
 @Validated
 @Builder
-public record OzgUploadFile(OzgCloudUploadFile fileData, InputStream fileContent) {
+public record OzgUploadFile(String vorgangId, MultipartFile file) {
 }
diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/ChunkedFileSender.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/RestChunkedFileSender.java
similarity index 58%
rename from server/src/main/java/de/ozgcloud/antragsraum/attachments/ChunkedFileSender.java
rename to server/src/main/java/de/ozgcloud/antragsraum/attachments/RestChunkedFileSender.java
index ac2b961157598151ef985865988374c69189c547..a2b0cd49cf2d1848b067535a740a1092b215d39e 100644
--- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/ChunkedFileSender.java
+++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/RestChunkedFileSender.java
@@ -22,48 +22,80 @@
 
 package de.ozgcloud.antragsraum.attachments;
 
-import de.ozgcloud.antragsraum.common.TechnicalException;
-import io.grpc.stub.CallStreamObserver;
-import lombok.AllArgsConstructor;
-import lombok.extern.log4j.Log4j2;
-import org.apache.commons.io.IOUtils;
+import static de.ozgcloud.antragsraum.WebConfiguration.*;
+import static de.ozgcloud.antragsraum.attachments.FileRestClient.*;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Function;
 
+import org.apache.commons.io.IOUtils;
+import org.springframework.http.MediaType;
+import org.springframework.web.client.RestClient;
+
+import de.ozgcloud.antragsraum.common.TechnicalException;
+import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcUploadBinaryFileResponse;
+import lombok.AllArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
 @Log4j2
 @AllArgsConstructor
-class ChunkedFileSender<T> {
+class RestChunkedFileSender<T> {
 	private final AtomicBoolean hasUploadFile = new AtomicBoolean(true);
 	private final InputStream uploadStream;
 	private final int chunkSize;
 	private final Function<byte[], T> buildChunkRequest;
 	private T requestMetadata;
+	private final RestClient restClient;
+	private String targetAddress;
+	private final CompletableFuture<String> fileIdFuture;
 
-	public void sendChunkTo(CallStreamObserver<T> streamObserver) {
+	public void sendChunkTo() {
 		if (hasUploadFile.get()) {
-			sendMetadata(streamObserver);
-			int size = sendNextChunk(streamObserver);
+			var response = sendMetadata();
+			int size = sendNextChunk();
 			if (size < chunkSize) {
-				handleFileEndReached(streamObserver);
+				handleFileEndReached();
+				fileIdFuture.complete(response.getFileId());
 			}
 		}
 	}
 
-	private void sendMetadata(CallStreamObserver<T> streamObserver) {
+	private AntragraumproxyGrpcUploadBinaryFileResponse sendMetadata() {
 		if (requestMetadata != null) {
-			streamObserver.onNext(requestMetadata);
+			var res = restClient
+			  .post()
+			  .uri(UPLOAD_FILE_API)
+			  .header(X_GRPC_ADDRESS, targetAddress)
+			  .contentType(MediaType.APPLICATION_JSON)
+			  .body(requestMetadata)
+			  .retrieve().toEntity(AntragraumproxyGrpcUploadBinaryFileResponse.class).getBody();
+			LOG.info("recieved {}", res);
+
 			requestMetadata = null;
+
+			return res;
 		}
+
+		return null;
 	}
 
-	private int sendNextChunk(CallStreamObserver<T> streamObserver) {
+	private int sendNextChunk() {
 		byte[] content = readFromStream();
 		var size = content.length;
 		if (size > 0) {
-			streamObserver.onNext(buildChunkRequest.apply(content));
+			var restUploadFile = buildChunkRequest.apply(content);
+			var res = restClient
+			  .post()
+			  .uri(UPLOAD_FILE_API)
+			  .header(X_GRPC_ADDRESS, targetAddress)
+			  .contentType(MediaType.APPLICATION_JSON)
+			  .body(restUploadFile)
+			  .retrieve().toEntity(AntragraumproxyGrpcUploadBinaryFileResponse.class);
+
+			LOG.info("Send binary chunk result: {}", res);
 		}
 		return size;
 	}
@@ -77,9 +109,9 @@ class ChunkedFileSender<T> {
 		}
 	}
 
-	private void handleFileEndReached(CallStreamObserver<T> streamObserver) {
+	private void handleFileEndReached() {
 		IOUtils.closeQuietly(uploadStream);
-		streamObserver.onCompleted();
+
 		hasUploadFile.getAndSet(false);
 	}
 }
diff --git a/server/src/main/resources/application-local.yml b/server/src/main/resources/application-local.yml
index fcc20fc6f6bdea5caeaf3f2bf4854aa81d716d5d..dd87a88dc3cbdae321115bfcc17871c9faa65746 100644
--- a/server/src/main/resources/application-local.yml
+++ b/server/src/main/resources/application-local.yml
@@ -11,9 +11,9 @@ clamav:
 
 logging:
   level:
-    "org.springframework.security": DEBUG
+    "org.springframework.security": WARN
     "org.springframework.security.access": WARN
-    "org.springframework.http": DEBUG
+    "org.springframework.http": INFO
     "org.springframework.web": DEBUG
     "org.springframework.web.client": DEBUG
     "de.ozgcloud.antragsraum": DEBUG
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/ChunkedFileSenderTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/ChunkedFileSenderTest.java
deleted file mode 100644
index 64ba29a6b8127ca300cb36c1a25b5f1d7287dca4..0000000000000000000000000000000000000000
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/ChunkedFileSenderTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2024.   Das Land Schleswig-Holstein vertreten durch den Ministerpräsidenten
- * des Landes Schleswig-Holstein Staatskanzlei Abteilung Digitalisierung und zentrales IT-Management der Landesregierung.
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-
-package de.ozgcloud.antragsraum.attachments;
-
-import static org.mockito.Mockito.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Spy;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import com.google.protobuf.ByteString;
-
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import io.grpc.stub.ClientCallStreamObserver;
-
-@ExtendWith(MockitoExtension.class)
-class ChunkedFileSenderTest {
-
-	private ChunkedFileSender<GrpcUploadBinaryFileRequest> chunkedFileSender;
-
-	@Spy
-	InputStream inputStream = OzgUploadFileTestFactory.create().fileContent();
-
-	@BeforeEach
-	void setUp() {
-		var metaDataRequest = GrpcUploadBinaryFileRequest.newBuilder().build();
-
-		chunkedFileSender = spy(new ChunkedFileSender<>(inputStream, FileGrpcClient.CHUNK_SIZE,
-		  this::buildChunkRequest, metaDataRequest));
-	}
-
-	GrpcUploadBinaryFileRequest buildChunkRequest(byte[] bytes) {
-		return GrpcUploadBinaryFileRequest.newBuilder().setFileContent((ByteString.copyFrom(bytes))).build();
-	}
-
-	@Nested
-	class TestSendingFileChunks {
-		@Test
-		@SuppressWarnings("unchecked")
-		void shouldCallOnNext() {
-			var observer = mock(ClientCallStreamObserver.class);
-
-			chunkedFileSender.sendChunkTo(observer);
-
-			verify(observer, atLeast(1)).onNext(any());
-		}
-
-		@Test
-		@SuppressWarnings("unchecked")
-		void shouldCallOnCompleted() {
-			var observer = mock(ClientCallStreamObserver.class);
-
-			chunkedFileSender.sendChunkTo(observer);
-
-			verify(observer).onCompleted();
-		}
-
-		@Test
-		@SuppressWarnings("unchecked")
-		void shouldCallReadNBytes() throws IOException {
-			var observer = mock(ClientCallStreamObserver.class);
-
-			chunkedFileSender.sendChunkTo(observer);
-
-			verify(inputStream).readNBytes(anyInt());
-		}
-
-		@Test
-		@SuppressWarnings("unchecked")
-		void shouldCallInputStreamClose() throws IOException {
-			var observer = mock(ClientCallStreamObserver.class);
-
-			chunkedFileSender.sendChunkTo(observer);
-
-			verify(inputStream).close();
-		}
-	}
-}
\ No newline at end of file
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerITCase.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerITCase.java
index 3f0d52ee4e3357eb8d02d09cef3d5677f410a83f..374a5c968a203a6ce23f33e8715c64abf895ce5f 100644
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerITCase.java
+++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerITCase.java
@@ -21,8 +21,8 @@
 package de.ozgcloud.antragsraum.attachments;
 
 import static de.ozgcloud.antragsraum.attachments.FileController.*;
-import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*;
 import static de.ozgcloud.antragsraum.attachments.FileValidatorTest.*;
+import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*;
 import static org.hamcrest.Matchers.*;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.*;
@@ -49,6 +49,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.MvcResult;
 import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.web.client.RestClient;
 import org.springframework.web.client.RestTemplate;
 
 import de.ozgcloud.antragsraum.common.NotFoundException;
@@ -69,6 +70,9 @@ public class FileControllerITCase {
 	@MockBean
 	private RestTemplate restTemplate;
 
+	@MockBean
+	private RestClient restClient;
+
 	@Autowired
 	private MockMvc mockMvc;
 
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileDownloadStreamObserverTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileDownloadStreamObserverTest.java
deleted file mode 100644
index e03c730c85c2bb5357f7c53611bfde03316fec8a..0000000000000000000000000000000000000000
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileDownloadStreamObserverTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 de.ozgcloud.antragsraum.attachments;
-
-import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*;
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.concurrent.CompletableFuture;
-
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import com.google.protobuf.ByteString;
-
-import de.ozgcloud.antragsraum.common.TechnicalException;
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
-
-@ExtendWith(MockitoExtension.class)
-class FileDownloadStreamObserverTest {
-	@InjectMocks
-	private FileDownloadStreamObserver downloadStreamObserver;
-	@Mock
-	private CompletableFuture<Boolean> streamFuture;
-	@Mock
-	private OutputStream out;
-
-	@Nested
-	class TestOnNext {
-		@Test
-		void shouldWriteToStreamOnReceivingContentPart() throws IOException {
-			downloadStreamObserver.onNext(createFileContentResponse());
-
-			verify(out).write(DATA);
-		}
-
-		private GrpcGetBinaryFileDataResponse createFileContentResponse() {
-			return GrpcGetBinaryFileDataResponse.newBuilder().setFileContent(ByteString.copyFrom(DATA)).build();
-		}
-
-		@Test
-		void shouldHandleException() throws IOException {
-			doThrow(IOException.class).when(out).write(any());
-
-			assertThatExceptionOfType(TechnicalException.class).isThrownBy(
-			  () -> downloadStreamObserver.onNext(createFileContentResponse())).withMessage("TechnicalException happened! Message: null");
-		}
-	}
-
-	@Nested
-	class TestOnError {
-		@Mock
-		private Throwable throwable;
-
-		@Test
-		void shouldCompleteFutureExceptionally() {
-			downloadStreamObserver.onError(throwable);
-
-			verify(streamFuture).completeExceptionally(throwable);
-		}
-	}
-
-	@Nested
-	class TestOnCompleted {
-		@Test
-		void shouldCompleteFuture() {
-			downloadStreamObserver.onCompleted();
-
-			verify(streamFuture).complete(true);
-		}
-	}
-}
\ No newline at end of file
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileGrpcClientTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileGrpcClientTest.java
deleted file mode 100644
index 35c1a5b3f034d87ff685f7f1324c7a8e4953712a..0000000000000000000000000000000000000000
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileGrpcClientTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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 de.ozgcloud.antragsraum.attachments;
-
-import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*;
-import static org.assertj.core.api.Assertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Spy;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import com.google.protobuf.ByteString;
-
-import de.ozgcloud.antragsraum.callcontext.ContextService;
-import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc;
-import de.ozgcloud.vorgang.grpc.command.GrpcCallContext;
-
-@ExtendWith(MockitoExtension.class)
-@Disabled("Needs to be fixed when switched to rest")
-class FileGrpcClientTest {
-	@Spy
-	@InjectMocks
-	private FileGrpcClient fileGrpcClient;
-
-	@Mock
-	private ContextService contextService;
-
-	@Nested
-	class TestDownloadObserver {
-		@Test
-		void shouldCreateDownloadObserver() {
-			var observer = fileGrpcClient.createDownloadFileObserver(CompletableFuture.completedFuture(Boolean.TRUE), new ByteArrayOutputStream());
-
-			assertThat(observer).isNotNull();
-		}
-	}
-
-	@Nested
-	class TestUploadingFile {
-		@Mock
-		private BinaryFileServiceGrpc.BinaryFileServiceStub asyncStub;
-
-		private final OzgUploadFile file = OzgUploadFileTestFactory.create();
-
-		CompletableFuture<String> fileIdFuture = new CompletableFuture<>();
-
-		@BeforeEach
-		void init() {
-			when(contextService.createCallContext()).thenReturn(GrpcCallContext.newBuilder().build());
-		}
-
-		@Test
-		void shouldCallGetChannel() {
-			fileGrpcClient.uploadFile(file, CHANNEL_ADDRESS, fileIdFuture);
-		}
-
-		@Test
-		void shouldCallBuildCallStreamObserver() {
-			fileGrpcClient.uploadFile(file, CHANNEL_ADDRESS, fileIdFuture);
-
-			verify(fileGrpcClient).createUploadFileObserver(any(), any());
-		}
-	}
-
-	@Nested
-	class TestBuildChunkRequest {
-		@Test
-		void shouldContainContent() {
-			var chunkRequest = fileGrpcClient.buildChunkRequest(DATA);
-
-			assertThat(chunkRequest.getFileContent()).isEqualTo(ByteString.copyFrom(DATA));
-		}
-	}
-
-	@Nested
-	class TestDownloadingFiles {
-		@Mock
-		private FileDownloadStreamObserver responseObserver;
-
-		@Mock
-		private BinaryFileServiceGrpc.BinaryFileServiceStub asyncStub;
-
-		private final ByteArrayOutputStream output = new ByteArrayOutputStream();
-
-		@BeforeEach
-		void init() {
-			doReturn(responseObserver).when(fileGrpcClient).createDownloadFileObserver(any(), any(OutputStream.class));
-			doNothing().when(fileGrpcClient).waitUntilFutureToComplete(any());
-		}
-
-		@Test
-		void shouldCallCreateDownloadFileObserver() {
-			fileGrpcClient.downloadFileContent(FILE_ID, output, CHANNEL_ADDRESS);
-
-			verify(fileGrpcClient).createDownloadFileObserver(any(), any(OutputStream.class));
-		}
-	}
-
-	@Nested
-	class TestWaitUntilFutureToComplete {
-		@Mock
-		private CompletableFuture<Boolean> streamFuture;
-
-		@Test
-		void shouldNotThrowException() {
-			assertDoesNotThrow(() -> fileGrpcClient.waitUntilFutureToComplete(streamFuture));
-		}
-
-		@ParameterizedTest
-		@ValueSource(classes = { InterruptedException.class, ExecutionException.class, TimeoutException.class })
-		void shouldRethrowAsRuntimeException(Class<Exception> exception)
-		  throws InterruptedException, ExecutionException, TimeoutException {
-			doThrow(exception).when(streamFuture).get(anyLong(), any(TimeUnit.class));
-
-			assertThrows(RuntimeException.class, () -> fileGrpcClient.waitUntilFutureToComplete(streamFuture));
-		}
-	}
-}
\ No newline at end of file
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileGrpcTestConfiguration.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileGrpcTestConfiguration.java
index d2e9348f4def6a6757357707af309b2936b71de3..8eb0b43f1cd2b10e7cd8282a84d63809a88e7543 100644
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileGrpcTestConfiguration.java
+++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileGrpcTestConfiguration.java
@@ -25,6 +25,7 @@ package de.ozgcloud.antragsraum.attachments;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestClient;
 
 import de.ozgcloud.antragsraum.callcontext.ContextService;
 import de.ozgcloud.antragsraum.common.AuthenticationHelper;
@@ -33,13 +34,13 @@ import lombok.NonNull;
 @Configuration
 public class FileGrpcTestConfiguration {
 	@Bean
-	FileGrpcClient fileGrpcClient() {
-		return new FileGrpcClient(contextProvider());
+	FileRestClient fileRestClient() {
+		return new FileRestClient(contextProvider(), RestClient.builder().baseUrl("http://localhost:8080").build());
 	}
 
 	@Bean
-	FileRemoteService fileRemoteService(@Autowired FileGrpcClient fileGrpcClient) {
-		return new FileRemoteService(fileGrpcClient);
+	FileRemoteService fileRemoteService(@Autowired FileRestClient fileRestClient) {
+		return new FileRemoteService(fileRestClient);
 	}
 
 	@NonNull
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTest.java
index b32d69abd87ad219e7bbdaf0ae8d98b437b98f98..4d337cf57354e5850c6fec2e1532b5f83fdeebcb 100644
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTest.java
+++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTest.java
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.*;
 
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
+import java.util.List;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
@@ -40,9 +41,8 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.mockito.junit.jupiter.MockitoExtension;
 
-import de.ozgcloud.vorgang.grpc.binaryFile.GrpcFindFilesResponse;
-import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
-import io.grpc.stub.StreamObserver;
+import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcFindFilesResponse;
+import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcOzgFile;
 
 @ExtendWith(MockitoExtension.class)
 class FileRemoteServiceTest {
@@ -51,20 +51,21 @@ class FileRemoteServiceTest {
 	private FileRemoteService remoteService;
 
 	@Mock
-	private FileGrpcClient grpcClient;
+	private FileRestClient restClient;
 
 	@Nested
 	class TestLoadingFile {
 
 		@BeforeEach
 		void init() {
-			var file = GrpcOzgFile.newBuilder()
-			  .setName(FILE_NAME)
-			  .setSize(FILE_SIZE)
-			  .setContentType(CONTENT_TYPE)
-			  .setId(FILE_ID).build();
-			when(grpcClient.findBinaryFilesMetaData(any(), any())).thenReturn(
-			  GrpcFindFilesResponse.newBuilder().addFile(file).build());
+			var response = new AntragraumproxyGrpcFindFilesResponse();
+			var file = new AntragraumproxyGrpcOzgFile();
+			file.setName(FILE_NAME);
+			file.setSize(FILE_SIZE_STRING);
+			file.setContentType(CONTENT_TYPE);
+			file.setId(FILE_ID);
+			response.setFile(List.of(file));
+			when(restClient.findBinaryFilesMetaData(any(), any())).thenReturn(response);
 		}
 
 		@Test
@@ -104,8 +105,8 @@ class FileRemoteServiceTest {
 
 		@Test
 		void shouldHandleEmpty() {
-			when(grpcClient.findBinaryFilesMetaData(any(), any())).thenReturn(
-			  GrpcFindFilesResponse.newBuilder().build());
+			var response = new AntragraumproxyGrpcFindFilesResponse();
+			when(restClient.findBinaryFilesMetaData(any(), any())).thenReturn(response);
 
 			var file = remoteService.getFile(FILE_ID, CHANNEL_ADDRESS);
 
@@ -119,10 +120,10 @@ class FileRemoteServiceTest {
 		private final ByteArrayOutputStream output = new ByteArrayOutputStream();
 
 		@Test
-		void shouldCallDownloadFileObserver() {
+		void shouldCallDownloadFileObserver() throws Exception {
 			remoteService.downloadFileContent(FILE_ID, output, CHANNEL_ADDRESS);
 
-			verify(grpcClient).downloadFileContent(eq(FILE_ID), any(OutputStream.class), eq(CHANNEL_ADDRESS));
+			verify(restClient).downloadFileContent(eq(FILE_ID), any(OutputStream.class), eq(CHANNEL_ADDRESS));
 		}
 	}
 
@@ -130,14 +131,10 @@ class FileRemoteServiceTest {
 	class TestUploadFile {
 
 		@Test
-		void shouldCallGrpcClient() {
-			var observer = mock(StreamObserver.class);
-
-			when(grpcClient.uploadFile(any(OzgUploadFile.class), eq(CHANNEL_ADDRESS), any())).thenReturn(observer);
-
+		void shouldCallRestClient() {
 			remoteService.uploadFile(OzgUploadFileTestFactory.create(), CHANNEL_ADDRESS);
 
-			verify(grpcClient).uploadFile(any(OzgUploadFile.class), eq(CHANNEL_ADDRESS), any());
+			verify(restClient).uploadFile(any(OzgUploadFile.class), eq(CHANNEL_ADDRESS), any());
 		}
 	}
 }
\ No newline at end of file
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileServiceTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileServiceTest.java
index 51727bb2b3f4a8804ca47197c386e6b1081b6461..e0b3260d71a1f8e1e5d49b4973c13d6364fb39be 100644
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileServiceTest.java
+++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileServiceTest.java
@@ -24,7 +24,6 @@ import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -37,11 +36,9 @@ import java.util.concurrent.TimeoutException;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
-import org.mockito.junit.jupiter.MockitoExtension;
 import org.springframework.web.multipart.MultipartFile;
 
 import de.ozgcloud.antragsraum.common.TechnicalException;
@@ -49,7 +46,6 @@ import de.ozgcloud.antragsraum.common.VirusFoundException;
 import de.ozgcloud.antragsraum.events.NachrichtEventService;
 import de.ozgcloud.antragsraum.events.NachrichtEventTestFactory;
 
-@ExtendWith(MockitoExtension.class)
 class FileServiceTest {
 	@Spy
 	@InjectMocks
@@ -66,14 +62,14 @@ class FileServiceTest {
 
 	@Nested
 	class TestFileUpload {
-		@Mock
-		private MultipartFile multipartFile;
+		@Spy
+		private MultipartFile multipartFile = OzgUploadFileTestFactory.MULTIPART_FILE;
 
 		@BeforeEach
 		void init() throws IOException {
 			when(remoteService.uploadFile(any(OzgUploadFile.class), anyString())).thenReturn(
 			  CompletableFuture.completedFuture(FILE_ID));
-			when(multipartFile.getInputStream()).thenReturn(new ByteArrayInputStream(DATA));
+
 			when(nachrichtEventService.getNachrichtEventById(NACHRICHT_EVENT_ID)).thenReturn(NachrichtEventTestFactory.createNachrichtEvent());
 		}
 
@@ -98,16 +94,16 @@ class FileServiceTest {
 
 	@Nested
 	class TestExceptionWhenSendingFile {
-		@Mock
-		private MultipartFile multipartFile;
+		@Spy
+		private final MultipartFile multipartFile = OzgUploadFileTestFactory.MULTIPART_FILE;
 
 		@Test
-		void shouldThrowTechnicalExceptionOnUpload() throws IOException {
-			doThrow(IOException.class).when(multipartFile).getInputStream();
+		void shouldThrowTechnicalExceptionOnUpload() {
+			when(nachrichtEventService.getNachrichtEventById(NACHRICHT_EVENT_ID)).thenReturn(NachrichtEventTestFactory.createNachrichtEvent());
+			doThrow(TechnicalException.class).when(remoteService).uploadFile(any(), anyString());
 
 			assertThatExceptionOfType(TechnicalException.class).isThrownBy(
-				() -> fileService.upload(VORGANG_ID, NACHRICHT_EVENT_ID, multipartFile))
-			  .withMessage("TechnicalException happened! Message: null");
+			  () -> fileService.upload(VORGANG_ID, NACHRICHT_EVENT_ID, multipartFile));
 		}
 	}
 
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/GrpcOzgFileTestFactory.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/GrpcOzgFileTestFactory.java
index 62f361aa5b175e2a0016503e62d869a3497b2682..d9b9dc223df6ce0896bfaf3c23bcc0480fd5e918 100644
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/GrpcOzgFileTestFactory.java
+++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/GrpcOzgFileTestFactory.java
@@ -22,18 +22,16 @@ package de.ozgcloud.antragsraum.attachments;
 
 import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*;
 
-import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
+import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcOzgFile;
 
 public class GrpcOzgFileTestFactory {
-	static GrpcOzgFile create() {
-		return createBuilder().build();
-	}
+	static AntragraumproxyGrpcOzgFile create() {
+		var file = new AntragraumproxyGrpcOzgFile();
+		file.setId(FILE_ID);
+		file.setContentType(CONTENT_TYPE);
+		file.setSize(FILE_SIZE_STRING);
+		file.setName(FILE_NAME);
 
-	static GrpcOzgFile.Builder createBuilder() {
-		return GrpcOzgFile.newBuilder()
-		  .setId(FILE_ID)
-		  .setContentType(CONTENT_TYPE)
-		  .setSize(FILE_SIZE)
-		  .setName(FILE_NAME);
+		return file;
 	}
 }
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileMapperTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileMapperTest.java
index 144e9223095bbdf1b102ec096fdbcd831724c034..b61e1e22334a5eb6b3ed2850a56d5901a932abd4 100644
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileMapperTest.java
+++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileMapperTest.java
@@ -28,37 +28,37 @@ import static org.assertj.core.api.Assertions.*;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
-import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
+import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcOzgFile;
 
 class OzgFileMapperTest {
 	@Nested
 	class TestMappingGrpcOzgFile {
-		private final GrpcOzgFile grpcOzgFile = GrpcOzgFileTestFactory.create();
+		private final AntragraumproxyGrpcOzgFile grpcOzgFile = GrpcOzgFileTestFactory.create();
 
 		@Test
 		void shouldHaveFileName() {
-			var file = OzgFileMapper.fromGrpcFile(grpcOzgFile);
+			var file = OzgFileMapper.fromRestFile(grpcOzgFile);
 
 			assertThat(file.fileName()).isEqualTo(FILE_NAME);
 		}
 
 		@Test
 		void shouldHaveFileSize() {
-			var file = OzgFileMapper.fromGrpcFile(grpcOzgFile);
+			var file = OzgFileMapper.fromRestFile(grpcOzgFile);
 
 			assertThat(file.fileSize()).isEqualTo(FILE_SIZE);
 		}
 
 		@Test
 		void shouldHaveContentType() {
-			var file = OzgFileMapper.fromGrpcFile(grpcOzgFile);
+			var file = OzgFileMapper.fromRestFile(grpcOzgFile);
 
 			assertThat(file.contentType()).isEqualTo(CONTENT_TYPE);
 		}
 
 		@Test
 		void shouldHaveFileId() {
-			var file = OzgFileMapper.fromGrpcFile(grpcOzgFile);
+			var file = OzgFileMapper.fromRestFile(grpcOzgFile);
 
 			assertThat(file.id()).isEqualTo(FILE_ID);
 		}
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileTestFactory.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileTestFactory.java
index 7ffd19c0f4eb69de55d103523e5e6b7253c7bc70..5621a8a567b722cb0fa9b8a3355b94c1106b5280 100644
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileTestFactory.java
+++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileTestFactory.java
@@ -29,6 +29,7 @@ public class OzgFileTestFactory {
 	static final String VORGANG_ID = UUID.randomUUID().toString();
 	static final String CONTENT_TYPE = ContentType.APPLICATION_OCTET_STREAM.toString();
 	static final long FILE_SIZE = 10;
+	static final String FILE_SIZE_STRING = String.valueOf(FILE_SIZE);
 	static final String FILE_NAME = "Testfile.pdf";
 	static final String NACHRICHT_EVENT_ID = UUID.randomUUID().toString();
 	static final String CHANNEL_ADDRESS = "static://localhost:9090";
diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgUploadFileTestFactory.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgUploadFileTestFactory.java
index 4fdcb9d201a0f6e9241a1ac2014de43bbefc001c..040bdd6d9660e967369f342433827aed70f0726e 100644
--- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgUploadFileTestFactory.java
+++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgUploadFileTestFactory.java
@@ -23,21 +23,69 @@ package de.ozgcloud.antragsraum.attachments;
 import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*;
 
 import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 
-import de.ozgcloud.apilib.file.OzgCloudUploadFile;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.http.MediaType;
+import org.springframework.web.multipart.MultipartFile;
 
 public class OzgUploadFileTestFactory {
+	public final static MultipartFile MULTIPART_FILE = new TestMultipartFile();
+
 	static OzgUploadFile create() {
 		return createBuilder().build();
 	}
 
 	static OzgUploadFile.OzgUploadFileBuilder createBuilder() {
 		return new OzgUploadFile.OzgUploadFileBuilder()
-		  .fileData(OzgCloudUploadFile.builder()
-			.fileName(FILE_NAME)
-			.contentType(CONTENT_TYPE)
-			.vorgangId(VORGANG_ID)
-			.build())
-		  .fileContent(new ByteArrayInputStream(DATA));
+		  .vorgangId(VORGANG_ID)
+		  .file(MULTIPART_FILE);
+	}
+
+	static class TestMultipartFile implements MultipartFile {
+		@Override
+		public @NotNull String getName() {
+			return "test.txt";
+		}
+
+		@Override
+		public String getOriginalFilename() {
+			return "test.txt";
+		}
+
+		@Override
+		public String getContentType() {
+			return MediaType.TEXT_PLAIN_VALUE;
+		}
+
+		@Override
+		public boolean isEmpty() {
+			return false;
+		}
+
+		@Override
+		public long getSize() {
+			return DATA.length;
+		}
+
+		@Override
+		public byte @NotNull [] getBytes() throws IOException {
+			return DATA.clone();
+		}
+
+		@Override
+		public @NotNull InputStream getInputStream() throws IOException {
+			return new ByteArrayInputStream(DATA);
+		}
+
+		@Override
+		public void transferTo(final @NotNull File dest) throws IOException, IllegalStateException {
+			try (FileOutputStream fos = new FileOutputStream(dest)) {
+				fos.write(DATA);
+			}
+		}
 	}
 }