diff --git a/api-data-store-server-java/src/main/java/ch/ethz/sis/afsclient/client/AfsClient.java b/api-data-store-server-java/src/main/java/ch/ethz/sis/afsclient/client/AfsClient.java
index 991bfd26bdc869aa79abf9ec81d6dc75af4de1e8..b7f1376048736af6608849715d34d183eee84586 100644
--- a/api-data-store-server-java/src/main/java/ch/ethz/sis/afsclient/client/AfsClient.java
+++ b/api-data-store-server-java/src/main/java/ch/ethz/sis/afsclient/client/AfsClient.java
@@ -1,11 +1,14 @@
 package ch.ethz.sis.afsclient.client;
 
+import ch.ethz.sis.afsapi.api.PublicAPI;
+import ch.ethz.sis.afsapi.dto.ApiResponse;
+import ch.ethz.sis.afsapi.dto.File;
+import ch.ethz.sis.afsclient.client.exception.ClientExceptions;
+import ch.ethz.sis.afsjson.JsonObjectMapper;
+import ch.ethz.sis.afsjson.jackson.JacksonObjectMapper;
+import lombok.NonNull;
+
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.net.Authenticator;
-import java.net.PasswordAuthentication;
 import java.net.URI;
 import java.net.URLEncoder;
 import java.net.http.HttpClient;
@@ -16,14 +19,6 @@ import java.time.Duration;
 import java.util.*;
 import java.util.stream.Stream;
 
-import ch.ethz.sis.afsapi.api.PublicAPI;
-import ch.ethz.sis.afsapi.dto.ApiResponse;
-import ch.ethz.sis.afsapi.dto.File;
-import ch.ethz.sis.afsclient.client.exception.ClientExceptions;
-import ch.ethz.sis.afsjson.JsonObjectMapper;
-import ch.ethz.sis.afsjson.jackson.JacksonObjectMapper;
-import lombok.NonNull;
-
 public final class AfsClient implements PublicAPI
 {
 
@@ -43,7 +38,7 @@ public final class AfsClient implements PublicAPI
 
     private final URI serverUri;
 
-    private final JsonObjectMapper jsonObjectMapper;
+    private static final JsonObjectMapper jsonObjectMapper = new JacksonObjectMapper();
 
     public AfsClient(final URI serverUri)
     {
@@ -55,7 +50,6 @@ public final class AfsClient implements PublicAPI
         this.maxReadSizeInBytes = maxReadSizeInBytes;
         this.timeout = timeout;
         this.serverUri = serverUri;
-        this.jsonObjectMapper = new JacksonObjectMapper();
     }
 
     public URI getServerUri()
@@ -107,9 +101,8 @@ public final class AfsClient implements PublicAPI
     public @NonNull String login(@NonNull final String userId, @NonNull final String password)
             throws Exception
     {
-        Map<String, String> credentials = Map.of("userId", userId, "password", password);
-        String result = request("POST", "login", Map.of(),
-                jsonObjectMapper.writeValue(credentials));
+        String result = request("POST",
+                "login", String.class, Map.of("userId", userId, "password", password));
         setSessionToken(result);
         return result;
     }
@@ -118,15 +111,14 @@ public final class AfsClient implements PublicAPI
     public @NonNull Boolean isSessionValid() throws Exception
     {
         validateSessionToken();
-        return request("GET", "isSessionValid", Map.of("sessionToken", getSessionToken()));
+        return request("GET", "isSessionValid", Boolean.class,Map.of());
     }
 
     @Override
     public @NonNull Boolean logout() throws Exception
     {
         validateSessionToken();
-        Boolean result = request("POST", "logout", Map.of(),
-                jsonObjectMapper.writeValue(Map.of("sessionToken", getSessionToken())));
+        Boolean result = request("POST", "logout", Boolean.class, Map.of());
         setSessionToken(null);
         return result;
     }
@@ -136,9 +128,9 @@ public final class AfsClient implements PublicAPI
             @NonNull final Boolean recursively) throws Exception
     {
         validateSessionToken();
-        return request("GET", "list",
+        return request("GET", "list", List.class,
                 Map.of("owner", owner, "source", source, "recursively",
-                        recursively.toString(), "sessionToken", getSessionToken()));
+                        recursively.toString()));
     }
 
     @Override
@@ -146,24 +138,19 @@ public final class AfsClient implements PublicAPI
             @NonNull final Long offset, @NonNull final Integer limit) throws Exception
     {
         validateSessionToken();
-        return request("GET", "read",
+        return request("GET", "read", byte[].class,
                 Map.of("owner", owner, "source", source, "offset",
-                        offset.toString(), "limit", limit.toString(), "sessionToken",
-                        getSessionToken()));
+                        offset.toString(), "limit", limit.toString()));
     }
 
     @Override
     public @NonNull Boolean write(@NonNull final String owner, @NonNull final String source,
-            @NonNull final Long offset, final byte @NonNull [] data,
-            final byte @NonNull [] md5Hash) throws Exception
+            @NonNull final Long offset, @NonNull final byte[] data,
+            @NonNull  final byte[] md5Hash) throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("owner", owner, "source", source,
-                        "offset", offset, "data", data, "md5Hash", md5Hash,
-                        "sessionToken", getSessionToken());
-
-        return request("POST", "write", Map.of(), jsonObjectMapper.writeValue(parameters));
+        return request("POST", "write", Boolean.class, Map.of("owner", owner, "source", source,
+                "offset", offset.toString(), "data", Base64.getEncoder().encodeToString(data), "md5Hash", Base64.getEncoder().encodeToString(md5Hash)));
     }
 
     @Override
@@ -171,11 +158,7 @@ public final class AfsClient implements PublicAPI
             throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("owner", owner, "source", source,
-                        "sessionToken", getSessionToken());
-
-        return request("DELETE", "delete", Map.of(), jsonObjectMapper.writeValue(parameters));
+        return request("DELETE", "delete", Boolean.class, Map.of("owner", owner, "source", source));
     }
 
     @Override
@@ -185,12 +168,8 @@ public final class AfsClient implements PublicAPI
             throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("sourceOwner", sourceOwner, "source", source,
-                        "targetOwner", targetOwner, "target", target,
-                        "sessionToken", getSessionToken());
-
-        return request("POST", "copy", Map.of(), jsonObjectMapper.writeValue(parameters));
+        return request("POST", "copy", Boolean.class, Map.of("sourceOwner", sourceOwner, "source", source,
+                "targetOwner", targetOwner, "target", target));
     }
 
     @Override
@@ -200,91 +179,107 @@ public final class AfsClient implements PublicAPI
             throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("sourceOwner", sourceOwner, "source", source,
-                        "targetOwner", targetOwner, "target", target,
-                        "sessionToken", getSessionToken());
-
-        return request("POST", "move", Map.of(), jsonObjectMapper.writeValue(parameters));
+        return request("POST", "move", Boolean.class, Map.of("sourceOwner", sourceOwner, "source", source,
+                "targetOwner", targetOwner, "target", target));
     }
 
     @Override
     public void begin(final UUID transactionId) throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("transactionId", transactionId.toString(),
-                        "sessionToken", getSessionToken(),
-                        "interactiveSessionKey", getInteractiveSessionKey());
-        request("POST", "begin", Map.of(), jsonObjectMapper.writeValue(parameters));
+        request("POST", "begin", null, Map.of("transactionId", transactionId.toString()));
     }
 
     @Override
     public Boolean prepare() throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("interactiveSessionKey", getInteractiveSessionKey(),
-                        "transactionManagerKey", getTransactionManagerKey());
-        return request("POST", "prepare", Map.of(), jsonObjectMapper.writeValue(parameters));
+        return request("POST", "prepare", Boolean.class, Map.of());
     }
 
     @Override
     public void commit() throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("interactiveSessionKey", getInteractiveSessionKey());
-        request("POST", "commit", Map.of(), jsonObjectMapper.writeValue(parameters));
+        request("POST", "commit", null, Map.of());
     }
 
     @Override
     public void rollback() throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("interactiveSessionKey", getInteractiveSessionKey());
-        request("POST", "rollback", Map.of(), jsonObjectMapper.writeValue(parameters));
+        request("POST", "rollback", null, Map.of());
     }
 
     @Override
     public List<UUID> recover() throws Exception
     {
         validateSessionToken();
-        Map<String, Object> parameters =
-                Map.of("interactiveSessionKey", getInteractiveSessionKey(),
-                        "transactionManagerKey", getTransactionManagerKey());
-        return request("POST", "recover", Map.of(), jsonObjectMapper.writeValue(parameters));
+        return request("POST", "recover", List.class, Map.of());
     }
 
-    private <T> T request(@NonNull final String httpMethod, @NonNull final String apiMethod,
-            @NonNull final Map<String, String> parameters) throws Exception
-    {
-        return request(httpMethod, apiMethod, parameters, new byte[0]);
-    }
 
     @SuppressWarnings({ "OptionalGetWithoutIsPresent", "unchecked" })
-    private <T> T request(@NonNull final String httpMethod, @NonNull final String apiMethod,
-            @NonNull final Map<String, String> parameters, final byte @NonNull [] body)
+    private <T> T request(@NonNull final String httpMethod, @NonNull final String apiMethod, Class<T> responseType,
+            @NonNull Map<String, String> params)
             throws Exception
     {
-        HttpClient.Builder clientBuilder = HttpClient.newBuilder()
-                .version(HttpClient.Version.HTTP_1_1)
-                .followRedirects(HttpClient.Redirect.NORMAL)
-                .connectTimeout(Duration.ofMillis(timeout));
-        Map<String, String> params = parameters;
+        //
+        // General Parameter Handling
+        //
 
-        HttpClient client = clientBuilder.build();
+        HashMap<String, String> mutableParams = new HashMap<>(params);
+        params = mutableParams;
+
+        if (sessionToken != null)
+        {
+            params.put("sessionToken", sessionToken);
+        }
+
+        if(interactiveSessionKey != null)
+        {
+            params.put("interactiveSessionKey", interactiveSessionKey);
+        }
+
+        if (transactionManagerKey != null)
+        {
+            params.put("transactionManagerKey", transactionManagerKey);
+        }
 
-        final String query = Stream.concat(
+        String parameters = Stream.concat(
                         Stream.of(new AbstractMap.SimpleImmutableEntry<>("method", apiMethod)),
                         params.entrySet().stream())
-                .map(entry -> urlEncode(entry.getKey()) + "=" + urlEncode(entry.getValue()))
+                .map(entry-> {
+                    return urlEncode(entry.getKey()) + "=" + urlEncode(entry.getValue());
+                })
                 .reduce((s1, s2) -> s1 + "&" + s2).get();
 
+        //
+        // GET Request - Parameters on the query string
+        //
+
+        String queryParameters = null;
+        if (httpMethod.equals("GET")) {
+            queryParameters = parameters;
+        }
+
+        //
+        // POST and DELETE Request - Parameters on body
+        //
+
+        byte[] body = null;
+        if (httpMethod.equals("POST") || httpMethod.equals("DELETE")) {
+            body = parameters.getBytes(StandardCharsets.UTF_8);
+        } else {
+            body = new byte[0];
+        }
+
+        //
+        // HTTP Client
+        //
         final URI uri =
                 new URI(serverUri.getScheme(), null, serverUri.getHost(), serverUri.getPort(),
-                        serverUri.getPath(), query, null);
+                        serverUri.getPath(), queryParameters, null);
 
         HttpRequest.Builder builder = HttpRequest.newBuilder()
                 .uri(uri)
@@ -294,6 +289,13 @@ public final class AfsClient implements PublicAPI
 
         final HttpRequest request = builder.build();
 
+        HttpClient.Builder clientBuilder = HttpClient.newBuilder()
+                .version(HttpClient.Version.HTTP_1_1)
+                .followRedirects(HttpClient.Redirect.NORMAL)
+                .connectTimeout(Duration.ofMillis(timeout));
+
+        HttpClient client = clientBuilder.build();
+
         final HttpResponse<byte[]> httpResponse =
                 client.send(request, HttpResponse.BodyHandlers.ofByteArray());
 
@@ -305,18 +307,10 @@ public final class AfsClient implements PublicAPI
                 throw new IllegalArgumentException(
                         "Server error HTTP response. Missing content-type");
             }
-            String content = httpResponse.headers().map().get("content-type").get(0);
+            String contentType = httpResponse.headers().map().get("content-type").get(0);
+            byte[] responseBody = httpResponse.body();
 
-            switch (content)
-            {
-                case "application/json":
-                    return parseJsonResponse(httpResponse);
-                case "application/octet-stream":
-                    return (T) httpResponse.body();
-                default:
-                    throw new IllegalArgumentException(
-                            "Client error HTTP response. Unsupported content-type received.");
-            }
+            return getResponseResult(responseType, contentType, responseBody);
         } else if (statusCode >= 400 && statusCode < 500)
         {
             // jsonObjectMapper can't deserialize immutable lists sent in the error message.
@@ -331,10 +325,40 @@ public final class AfsClient implements PublicAPI
         }
     }
 
-    private <T> T parseJsonResponse(final HttpResponse<byte[]> httpResponse) throws Exception
+    public static <T> T getResponseResult(Class<T> responseType, String contentType, byte[] responseBody)
+            throws Exception
+    {
+        switch (contentType)
+        {
+            case "text/plain":
+                return AfsClient.parseFormDataResponse(responseType, responseBody);
+            case "application/json":
+                return AfsClient.parseJsonResponse(responseBody);
+            case "application/octet-stream":
+                return (T) responseBody;
+            default:
+                throw new IllegalArgumentException(
+                        "Client error HTTP response. Unsupported content-type received.");
+        }
+    }
+
+    private static <T> T parseFormDataResponse(Class<T> responseType, byte[] responseBody)
+    {
+        if (responseType == null) {
+            return null;
+        } else if (responseType == String.class) {
+            return responseType.cast(new String(responseBody, StandardCharsets.UTF_8));
+        } else if (responseType == Boolean.class) {
+            return  responseType.cast(Boolean.parseBoolean(new String(responseBody, StandardCharsets.UTF_8)));
+        }
+
+        throw new IllegalStateException("Unreachable statement!");
+    }
+
+    private static <T> T parseJsonResponse(byte[] responseBody) throws Exception
     {
         final ApiResponse response =
-                jsonObjectMapper.readValue(new ByteArrayInputStream(httpResponse.body()),
+                jsonObjectMapper.readValue(new ByteArrayInputStream(responseBody),
                         ApiResponse.class);
 
         if (response.getError() != null)
@@ -353,5 +377,4 @@ public final class AfsClient implements PublicAPI
             throw new IllegalStateException("No session information detected!");
         }
     }
-
 }
diff --git a/api-data-store-server-java/src/main/java/ch/ethz/sis/afsclient/client/AfsClientV2.java b/api-data-store-server-java/src/main/java/ch/ethz/sis/afsclient/client/AfsClientV2.java
deleted file mode 100644
index aa456946a960d8562a75a5d28c8700730cfb07f8..0000000000000000000000000000000000000000
--- a/api-data-store-server-java/src/main/java/ch/ethz/sis/afsclient/client/AfsClientV2.java
+++ /dev/null
@@ -1,376 +0,0 @@
-package ch.ethz.sis.afsclient.client;
-
-import ch.ethz.sis.afsapi.api.PublicAPI;
-import ch.ethz.sis.afsapi.dto.ApiResponse;
-import ch.ethz.sis.afsapi.dto.File;
-import ch.ethz.sis.afsclient.client.exception.ClientExceptions;
-import ch.ethz.sis.afsjson.JsonObjectMapper;
-import ch.ethz.sis.afsjson.jackson.JacksonObjectMapper;
-import lombok.NonNull;
-
-import java.io.ByteArrayInputStream;
-import java.math.BigInteger;
-import java.net.URI;
-import java.net.URLEncoder;
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.nio.charset.StandardCharsets;
-import java.time.Duration;
-import java.util.*;
-import java.util.stream.Stream;
-
-public final class AfsClientV2 implements PublicAPI
-{
-
-    private static final int DEFAULT_PACKAGE_SIZE_IN_BYTES = 1024;
-
-    private static final int DEFAULT_TIMEOUT_IN_MILLIS = 30000;
-
-    private final int maxReadSizeInBytes;
-
-    private final int timeout;
-
-    private String sessionToken;
-
-    private String interactiveSessionKey;
-
-    private String transactionManagerKey;
-
-    private final URI serverUri;
-
-    private static final JsonObjectMapper jsonObjectMapper = new JacksonObjectMapper();
-
-    public AfsClientV2(final URI serverUri)
-    {
-        this(serverUri, DEFAULT_PACKAGE_SIZE_IN_BYTES, DEFAULT_TIMEOUT_IN_MILLIS);
-    }
-
-    public AfsClientV2(final URI serverUri, final int maxReadSizeInBytes, final int timeout)
-    {
-        this.maxReadSizeInBytes = maxReadSizeInBytes;
-        this.timeout = timeout;
-        this.serverUri = serverUri;
-    }
-
-    public URI getServerUri()
-    {
-        return serverUri;
-    }
-
-    public int getMaxReadSizeInBytes()
-    {
-        return maxReadSizeInBytes;
-    }
-
-    public String getSessionToken()
-    {
-        return sessionToken;
-    }
-
-    public void setSessionToken(final String sessionToken)
-    {
-        this.sessionToken = sessionToken;
-    }
-
-    public String getInteractiveSessionKey()
-    {
-        return interactiveSessionKey;
-    }
-
-    public void setInteractiveSessionKey(String interactiveSessionKey)
-    {
-        this.interactiveSessionKey = interactiveSessionKey;
-    }
-
-    public String getTransactionManagerKey()
-    {
-        return transactionManagerKey;
-    }
-
-    public void setTransactionManagerKey(String transactionManagerKey)
-    {
-        this.transactionManagerKey = transactionManagerKey;
-    }
-
-    private static String urlEncode(final String s)
-    {
-        return URLEncoder.encode(s, StandardCharsets.UTF_8);
-    }
-
-    @Override
-    public @NonNull String login(@NonNull final String userId, @NonNull final String password)
-            throws Exception
-    {
-        String result = request("POST",
-                "login", String.class, Map.of("userId", userId, "password", password));
-        setSessionToken(result);
-        return result;
-    }
-
-    @Override
-    public @NonNull Boolean isSessionValid() throws Exception
-    {
-        validateSessionToken();
-        return request("GET", "isSessionValid", Boolean.class,Map.of());
-    }
-
-    @Override
-    public @NonNull Boolean logout() throws Exception
-    {
-        validateSessionToken();
-        Boolean result = request("POST", "logout", Boolean.class, Map.of());
-        setSessionToken(null);
-        return result;
-    }
-
-    @Override
-    public @NonNull List<File> list(@NonNull final String owner, @NonNull final String source,
-            @NonNull final Boolean recursively) throws Exception
-    {
-        validateSessionToken();
-        return request("GET", "list", List.class,
-                Map.of("owner", owner, "source", source, "recursively",
-                        recursively.toString()));
-    }
-
-    @Override
-    public @NonNull byte[] read(@NonNull final String owner, @NonNull final String source,
-            @NonNull final Long offset, @NonNull final Integer limit) throws Exception
-    {
-        validateSessionToken();
-        return request("GET", "read", byte[].class,
-                Map.of("owner", owner, "source", source, "offset",
-                        offset.toString(), "limit", limit.toString()));
-    }
-
-    @Override
-    public @NonNull Boolean write(@NonNull final String owner, @NonNull final String source,
-            @NonNull final Long offset, @NonNull final byte[] data,
-            @NonNull  final byte[] md5Hash) throws Exception
-    {
-        validateSessionToken();
-        return request("POST", "write", Boolean.class, Map.of("owner", owner, "source", source,
-                "offset", offset.toString(), "data", Base64.getEncoder().encodeToString(data), "md5Hash", Base64.getEncoder().encodeToString(md5Hash)));
-    }
-
-    @Override
-    public @NonNull Boolean delete(@NonNull final String owner, @NonNull final String source)
-            throws Exception
-    {
-        validateSessionToken();
-        return request("DELETE", "delete", Boolean.class, Map.of("owner", owner, "source", source));
-    }
-
-    @Override
-    public @NonNull Boolean copy(@NonNull final String sourceOwner, @NonNull final String source,
-            @NonNull final String targetOwner,
-            @NonNull final String target)
-            throws Exception
-    {
-        validateSessionToken();
-        return request("POST", "copy", Boolean.class, Map.of("sourceOwner", sourceOwner, "source", source,
-                "targetOwner", targetOwner, "target", target));
-    }
-
-    @Override
-    public @NonNull Boolean move(@NonNull final String sourceOwner, @NonNull final String source,
-            @NonNull final String targetOwner,
-            @NonNull final String target)
-            throws Exception
-    {
-        validateSessionToken();
-        return request("POST", "move", Boolean.class, Map.of("sourceOwner", sourceOwner, "source", source,
-                "targetOwner", targetOwner, "target", target));
-    }
-
-    @Override
-    public void begin(final UUID transactionId) throws Exception
-    {
-        validateSessionToken();
-        request("POST", "begin", null, Map.of("transactionId", transactionId.toString()));
-    }
-
-    @Override
-    public Boolean prepare() throws Exception
-    {
-        validateSessionToken();
-        return request("POST", "prepare", Boolean.class, Map.of());
-    }
-
-    @Override
-    public void commit() throws Exception
-    {
-        validateSessionToken();
-        request("POST", "commit", null, Map.of());
-    }
-
-    @Override
-    public void rollback() throws Exception
-    {
-        validateSessionToken();
-        request("POST", "rollback", null, Map.of());
-    }
-
-    @Override
-    public List<UUID> recover() throws Exception
-    {
-        validateSessionToken();
-        return request("POST", "recover", List.class, Map.of());
-    }
-
-
-    @SuppressWarnings({ "OptionalGetWithoutIsPresent", "unchecked" })
-    private <T> T request(@NonNull final String httpMethod, @NonNull final String apiMethod, Class<T> responseType,
-            @NonNull final Map<String, String> params)
-            throws Exception
-    {
-        //
-        // General Parameter Handling
-        //
-
-        if (sessionToken != null)
-        {
-            params.put("sessionToken", sessionToken);
-        }
-
-        if(interactiveSessionKey != null)
-        {
-            params.put("interactiveSessionKey", interactiveSessionKey);
-        }
-
-        if (transactionManagerKey != null)
-        {
-            params.put("transactionManagerKey", transactionManagerKey);
-        }
-
-        String parameters = Stream.concat(
-                        Stream.of(new AbstractMap.SimpleImmutableEntry<>("method", apiMethod)),
-                        params.entrySet().stream())
-                .map(entry-> {
-                    return urlEncode(entry.getKey()) + "=" + urlEncode(entry.getValue());
-                })
-                .reduce((s1, s2) -> s1 + "&" + s2).get();
-
-        //
-        // GET Request - Parameters on the query string
-        //
-
-        String queryParameters = null;
-        if (httpMethod.equals("GET")) {
-            queryParameters = parameters;
-        }
-
-        //
-        // POST Request - Parameters on body
-        //
-
-        byte[] body = null;
-        if (httpMethod.equals("POST")) {
-            body = parameters.getBytes(StandardCharsets.UTF_8);
-        }
-
-        //
-        // HTTP Client
-        //
-        final URI uri =
-                new URI(serverUri.getScheme(), null, serverUri.getHost(), serverUri.getPort(),
-                        serverUri.getPath(), queryParameters, null);
-
-        HttpRequest.Builder builder = HttpRequest.newBuilder()
-                .uri(uri)
-                .version(HttpClient.Version.HTTP_1_1)
-                .timeout(Duration.ofMillis(timeout))
-                .method(httpMethod, HttpRequest.BodyPublishers.ofByteArray(body));
-
-        final HttpRequest request = builder.build();
-
-        HttpClient.Builder clientBuilder = HttpClient.newBuilder()
-                .version(HttpClient.Version.HTTP_1_1)
-                .followRedirects(HttpClient.Redirect.NORMAL)
-                .connectTimeout(Duration.ofMillis(timeout));
-
-        HttpClient client = clientBuilder.build();
-
-        final HttpResponse<byte[]> httpResponse =
-                client.send(request, HttpResponse.BodyHandlers.ofByteArray());
-
-        final int statusCode = httpResponse.statusCode();
-        if (statusCode >= 200 && statusCode < 300)
-        {
-            if (!httpResponse.headers().map().containsKey("content-type"))
-            {
-                throw new IllegalArgumentException(
-                        "Server error HTTP response. Missing content-type");
-            }
-            String contentType = httpResponse.headers().map().get("content-type").get(0);
-            byte[] responseBody = httpResponse.body();
-
-            return getResponseResult(responseType, contentType, responseBody);
-        } else if (statusCode >= 400 && statusCode < 500)
-        {
-            // jsonObjectMapper can't deserialize immutable lists sent in the error message.
-            String res = new String(httpResponse.body(), StandardCharsets.UTF_8);
-            throw ClientExceptions.API_ERROR.getInstance(res);
-        } else if (statusCode >= 500 && statusCode < 600)
-        {
-            throw ClientExceptions.SERVER_ERROR.getInstance(statusCode);
-        } else
-        {
-            throw ClientExceptions.OTHER_ERROR.getInstance(statusCode);
-        }
-    }
-
-    public static <T> T getResponseResult(Class<T> responseType, String contentType, byte[] responseBody)
-            throws Exception
-    {
-        switch (contentType)
-        {
-            case "text/plain":
-                return AfsClientV2.parseFormDataResponse(responseType, responseBody);
-            case "application/json":
-                return AfsClientV2.parseJsonResponse(responseBody);
-            case "application/octet-stream":
-                return (T) responseBody;
-            default:
-                throw new IllegalArgumentException(
-                        "Client error HTTP response. Unsupported content-type received.");
-        }
-    }
-
-    private static <T> T parseFormDataResponse(Class<T> responseType, byte[] responseBody)
-    {
-        if (responseType == null) {
-            return null;
-        } else if (responseType == String.class) {
-            return responseType.cast(new String(responseBody, StandardCharsets.UTF_8));
-        } else if (responseType == Boolean.class) {
-            return  responseType.cast(Boolean.parseBoolean(new String(responseBody, StandardCharsets.UTF_8)));
-        }
-
-        throw new IllegalStateException("Unreachable statement!");
-    }
-
-    private static <T> T parseJsonResponse(byte[] responseBody) throws Exception
-    {
-        final ApiResponse response =
-                jsonObjectMapper.readValue(new ByteArrayInputStream(responseBody),
-                        ApiResponse.class);
-
-        if (response.getError() != null)
-        {
-            throw ClientExceptions.API_ERROR.getInstance(response.getError());
-        } else
-        {
-            return (T) response.getResult();
-        }
-    }
-
-    private void validateSessionToken()
-    {
-        if (getSessionToken() == null)
-        {
-            throw new IllegalStateException("No session information detected!");
-        }
-    }
-}
diff --git a/server-data-store/src/main/java/ch/ethz/sis/afsserver/http/impl/NettyHttpHandler.java b/server-data-store/src/main/java/ch/ethz/sis/afsserver/http/impl/NettyHttpHandler.java
index 50099d69e6814d9989fbe65405320b8403ef096c..30e08bc01fb665f47aa86b16a187039de83789de 100644
--- a/server-data-store/src/main/java/ch/ethz/sis/afsserver/http/impl/NettyHttpHandler.java
+++ b/server-data-store/src/main/java/ch/ethz/sis/afsserver/http/impl/NettyHttpHandler.java
@@ -27,7 +27,6 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.handler.codec.http.*;
 
 import java.nio.charset.StandardCharsets;
-import java.util.Base64;
 import java.util.Set;
 
 import static io.netty.handler.codec.http.HttpMethod.*;
@@ -59,18 +58,27 @@ public class NettyHttpHandler extends ChannelInboundHandlerAdapter
         if (msg instanceof FullHttpRequest)
         {
             final FullHttpRequest request = (FullHttpRequest) msg;
-            QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.uri(), true);
-            if (queryStringDecoder.path().equals(uri) &&
+            QueryStringDecoder queryStringDecoderForPath = new QueryStringDecoder(request.uri(), true);
+
+            if (queryStringDecoderForPath.path().equals(uri) &&
                     allowedMethods.contains(request.method()))
             {
                 FullHttpResponse response = null;
                 ByteBuf content = request.content();
                 try
                 {
+                    QueryStringDecoder queryStringDecoderForParameters = null;
                     byte[] array = new byte[content.readableBytes()];
                     content.readBytes(array);
+
+                    if (GET.equals(request.method())) {
+                        queryStringDecoderForParameters = queryStringDecoderForPath;
+                    } else {
+                        queryStringDecoderForParameters = new QueryStringDecoder(new String(array, StandardCharsets.UTF_8), StandardCharsets.UTF_8, false);
+                    }
+
                     HttpResponse apiResponse = httpServerHandler.process(request.method(),
-                            queryStringDecoder.parameters(), array);
+                            queryStringDecoderForParameters.parameters(), null);
                     HttpResponseStatus status = (!apiResponse.isError()) ?
                             HttpResponseStatus.OK :
                             HttpResponseStatus.BAD_REQUEST;
diff --git a/server-data-store/src/main/java/ch/ethz/sis/afsserver/http/impl/NettyHttpHandlerV2.java b/server-data-store/src/main/java/ch/ethz/sis/afsserver/http/impl/NettyHttpHandlerV2.java
deleted file mode 100644
index 5cb098e0a0626802c1fb869b180ff5fdd8154c89..0000000000000000000000000000000000000000
--- a/server-data-store/src/main/java/ch/ethz/sis/afsserver/http/impl/NettyHttpHandlerV2.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright ETH 2022 - 2023 Zürich, Scientific IT Services
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ch.ethz.sis.afsserver.http.impl;
-
-import ch.ethz.sis.afsserver.http.HttpResponse;
-import ch.ethz.sis.afsserver.http.HttpServerHandler;
-import ch.ethz.sis.shared.log.LogManager;
-import ch.ethz.sis.shared.log.Logger;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelFutureListener;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.handler.codec.http.*;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Set;
-
-import static io.netty.handler.codec.http.HttpMethod.*;
-
-public class NettyHttpHandlerV2 extends ChannelInboundHandlerAdapter
-{
-
-    private static final Logger logger = LogManager.getLogger(NettyHttpServer.class);
-
-    private static final byte[] NOT_FOUND = "404 NOT FOUND".getBytes();
-
-    private static final ByteBuf NOT_FOUND_BUFFER = Unpooled.wrappedBuffer(NOT_FOUND);
-
-    private static final Set<HttpMethod> allowedMethods = Set.of(GET, POST, PUT, DELETE);
-
-    private final String uri;
-
-    private final HttpServerHandler httpServerHandler;
-
-    public NettyHttpHandlerV2(String uri, HttpServerHandler httpServerHandler)
-    {
-        this.uri = uri;
-        this.httpServerHandler = httpServerHandler;
-    }
-
-    @Override
-    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
-    {
-        if (msg instanceof FullHttpRequest)
-        {
-            final FullHttpRequest request = (FullHttpRequest) msg;
-            QueryStringDecoder queryStringDecoderForPath = new QueryStringDecoder(request.uri(), true);
-
-            if (queryStringDecoderForPath.path().equals(uri) &&
-                    allowedMethods.contains(request.method()))
-            {
-                FullHttpResponse response = null;
-                ByteBuf content = request.content();
-                try
-                {
-                    QueryStringDecoder queryStringDecoderForParameters = null;
-                    byte[] array = new byte[content.readableBytes()];
-                    content.readBytes(array);
-
-                    if (GET.equals(request.method())) {
-                        queryStringDecoderForParameters = queryStringDecoderForPath;
-                    } else {
-                        queryStringDecoderForParameters = new QueryStringDecoder(new String(array, StandardCharsets.UTF_8), StandardCharsets.UTF_8, false);
-                    }
-
-                    HttpResponse apiResponse = httpServerHandler.process(request.method(),
-                            queryStringDecoderForParameters.parameters(), null);
-                    HttpResponseStatus status = (!apiResponse.isError()) ?
-                            HttpResponseStatus.OK :
-                            HttpResponseStatus.BAD_REQUEST;
-                    response = getHttpResponse(
-                            status,
-                            apiResponse.getContentType(),
-                            Unpooled.wrappedBuffer(apiResponse.getBody()),
-                            apiResponse.getBody().length);
-                    ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
-                } finally
-                {
-                    content.release();
-                }
-            } else
-            {
-                FullHttpResponse response = getHttpResponse(
-                        HttpResponseStatus.NOT_FOUND,
-                        "text/plain",
-                        NOT_FOUND_BUFFER,
-                        NOT_FOUND.length);
-                ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
-            }
-        } else
-        {
-            super.channelRead(ctx, msg);
-        }
-    }
-
-    @Override
-    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception
-    {
-        ctx.flush();
-    }
-
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
-    {
-        logger.catching(cause);
-        byte[] causeBytes = cause.getMessage().getBytes();
-        FullHttpResponse response = getHttpResponse(
-                HttpResponseStatus.INTERNAL_SERVER_ERROR,
-                "text/plain",
-                Unpooled.wrappedBuffer(causeBytes),
-                causeBytes.length
-        );
-        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
-    }
-
-    public FullHttpResponse getHttpResponse(
-            HttpResponseStatus status,
-            String contentType,
-            ByteBuf content,
-            int contentLength)
-    {
-        FullHttpResponse response = new DefaultFullHttpResponse(
-                HttpVersion.HTTP_1_1,
-                status,
-                content
-        );
-        response.headers().set(HttpHeaderNames.CONTENT_LENGTH, contentLength);
-        response.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
-        response.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType);
-        response.headers().set(HttpHeaderNames.CONNECTION, "close");
-        return response;
-    }
-}
diff --git a/server-data-store/src/main/java/ch/ethz/sis/afsserver/server/impl/ApiServerAdapter.java b/server-data-store/src/main/java/ch/ethz/sis/afsserver/server/impl/ApiServerAdapter.java
index 312d301a6835ed1cd07424fc9b42df6c091a4fe4..a56cd2d14c0bb8a574ddb54a7a43eeecebf15605 100644
--- a/server-data-store/src/main/java/ch/ethz/sis/afsserver/server/impl/ApiServerAdapter.java
+++ b/server-data-store/src/main/java/ch/ethz/sis/afsserver/server/impl/ApiServerAdapter.java
@@ -15,19 +15,25 @@
  */
 package ch.ethz.sis.afsserver.server.impl;
 
+import ch.ethz.sis.afsjson.JsonObjectMapper;
 import ch.ethz.sis.afsserver.exception.HTTPExceptions;
-import ch.ethz.sis.afsserver.http.*;
-import ch.ethz.sis.afsserver.server.*;
+import ch.ethz.sis.afsserver.http.HttpResponse;
+import ch.ethz.sis.afsserver.http.HttpServerHandler;
+import ch.ethz.sis.afsserver.server.APIServer;
+import ch.ethz.sis.afsserver.server.APIServerException;
+import ch.ethz.sis.afsserver.server.Request;
+import ch.ethz.sis.afsserver.server.Response;
 import ch.ethz.sis.afsserver.server.performance.Event;
 import ch.ethz.sis.afsserver.server.performance.PerformanceAuditor;
-import ch.ethz.sis.afsjson.JsonObjectMapper;
 import ch.ethz.sis.shared.log.LogManager;
 import ch.ethz.sis.shared.log.Logger;
 import io.netty.handler.codec.http.HttpMethod;
 
-import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.*;
 
+import static io.netty.handler.codec.http.HttpMethod.*;
+
 /*
  * This class is supposed to be called by a TCP or HTTP transport class
  */
@@ -58,7 +64,7 @@ public class ApiServerAdapter<CONNECTION, API> implements HttpServerHandler
             case "list":
             case "read":
             case "isSessionValid":
-                return HttpMethod.GET; // all parameters from GET methods come on the query string
+                return GET; // all parameters from GET methods come on the query string
             case "write":
             case "move":
             case "copy":
@@ -69,7 +75,7 @@ public class ApiServerAdapter<CONNECTION, API> implements HttpServerHandler
             case "commit":
             case "rollback":
             case "recover":
-                return HttpMethod.POST; // all parameters from POST methods come on the body
+                return POST; // all parameters from POST methods come on the body
             case "delete":
                 return HttpMethod.DELETE; // all parameters from DELETE methods come on the body
         }
@@ -82,7 +88,7 @@ public class ApiServerAdapter<CONNECTION, API> implements HttpServerHandler
         return correctMethod == givenMethod;
     }
 
-    public HttpResponse process(HttpMethod httpMethod, Map<String, List<String>> uriParameters,
+    public HttpResponse process(HttpMethod httpMethod, Map<String, List<String>> parameters,
             byte[] requestBody)
     {
         try
@@ -90,129 +96,90 @@ public class ApiServerAdapter<CONNECTION, API> implements HttpServerHandler
             logger.traceAccess(null);
             PerformanceAuditor performanceAuditor = new PerformanceAuditor();
 
+
+            if (httpMethod != GET && httpMethod != POST && httpMethod != DELETE)
+            {
+                return getHTTPResponse(new ApiResponse("1", null,
+                        HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
+            }
+
             String method = null;
             String sessionToken = null;
             String interactiveSessionKey = null;
             String transactionManagerKey = null;
             Map<String, Object> methodParameters = new HashMap<>();
-            if (HttpMethod.GET.equals(httpMethod))
-            {
-                for (Map.Entry<String, List<String>> entry : uriParameters.entrySet())
-                {
-                    String value = null;
-                    if (entry.getValue() != null)
-                    {
-                        if (entry.getValue().size() == 1)
-                        {
-                            value = entry.getValue().get(0);
-                        } else if (entry.getValue().size() > 1)
-                        {
-                            return getHTTPResponse(new ApiResponse("1", null,
-                                    HTTPExceptions.INVALID_PARAMETERS.getCause()));
-                        }
-                    }
 
-                    try
-                    {
-                        switch (entry.getKey())
-                        {
-                            case "method":
-                                method = value;
-                                if (!isValidMethod(httpMethod, method))
-                                {
-                                    return getHTTPResponse(new ApiResponse("1", null,
-                                            HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
-                                }
-                                break;
-                            case "sessionToken":
-                                sessionToken = value;
-                                break;
-                            case "interactiveSessionKey":
-                                interactiveSessionKey = value;
-                                break;
-                            case "transactionManagerKey":
-                                transactionManagerKey = value;
-                                break;
-                            case "transactionId":
-                                methodParameters.put(entry.getKey(), UUID.fromString(value));
-                                break;
-                            case "recursively":
-                                methodParameters.put(entry.getKey(), Boolean.valueOf(value));
-                                break;
-                            case "offset":
-                                methodParameters.put(entry.getKey(), Long.valueOf(value));
-                                break;
-                            case "limit":
-                                methodParameters.put(entry.getKey(), Integer.valueOf(value));
-                                break;
-                            default:
-                                methodParameters.put(entry.getKey(), value);
-                                break;
-                        }
-                    } catch (Exception e)
-                    {
-                        logger.catching(e);
-                        return getHTTPResponse(new ApiResponse("1", null,
-                                HTTPExceptions.INVALID_PARAMETERS.getCause(
-                                        e.getClass().getSimpleName(),
-                                        e.getMessage())));
-                    }
-                }
-            } else if (HttpMethod.POST.equals(httpMethod) || HttpMethod.DELETE.equals(httpMethod))
+            for (Map.Entry<String, List<String>> entry : parameters.entrySet())
             {
-                if (!uriParameters.containsKey("method"))
+                String value = null;
+                if (entry.getValue() != null)
                 {
-                    return getHTTPResponse(new ApiResponse("1", null,
-                            HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
-                } else
-                {
-                    List<String> methodParam = uriParameters.get("method");
-                    if (methodParam == null || methodParam.size() != 1)
+                    if (entry.getValue().size() == 1)
+                    {
+                        value = entry.getValue().get(0);
+                    } else if (entry.getValue().size() > 1)
                     {
                         return getHTTPResponse(new ApiResponse("1", null,
-                                HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
+                                HTTPExceptions.INVALID_PARAMETERS.getCause()));
                     }
-                    method = methodParam.get(0);
                 }
 
-                if (!isValidMethod(httpMethod, method))
-                {
-                    return getHTTPResponse(new ApiResponse("1", null,
-                            HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
-                }
-                Map<String, Object> bodyParameterMap = readBody(requestBody, HashMap.class);
-
-                for (Map.Entry<String, Object> entry : bodyParameterMap.entrySet())
+                try
                 {
                     switch (entry.getKey())
                     {
+                        case "method":
+                            method = value;
+                            if (!isValidMethod(httpMethod, method))
+                            {
+                                return getHTTPResponse(new ApiResponse("1", null,
+                                        HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
+                            }
+                            break;
                         case "sessionToken":
-                            sessionToken = (String) entry.getValue();
+                            sessionToken = value;
                             break;
                         case "interactiveSessionKey":
-                            interactiveSessionKey = (String) entry.getValue();
+                            interactiveSessionKey = value;
                             break;
                         case "transactionManagerKey":
-                            transactionManagerKey = (String) entry.getValue();
+                            transactionManagerKey = value;
                             break;
                         case "transactionId":
-                            methodParameters.put(entry.getKey(),
-                                    UUID.fromString((String) entry.getValue()));
+                            methodParameters.put(entry.getKey(), UUID.fromString(value));
+                            break;
+                        case "recursively":
+                            methodParameters.put(entry.getKey(), Boolean.valueOf(value));
+                            break;
+                        case "offset":
+                            methodParameters.put(entry.getKey(), Long.valueOf(value));
+                            break;
+                        case "limit":
+                            methodParameters.put(entry.getKey(), Integer.valueOf(value));
+                            break;
+                        case "data":
+                            methodParameters.put(entry.getKey(), Base64.getDecoder().decode(value));
+                            break;
+                        case "md5Hash":
+                            methodParameters.put(entry.getKey(), Base64.getDecoder().decode(value));
                             break;
                         default:
-                            methodParameters.put(entry.getKey(), entry.getValue());
+                            methodParameters.put(entry.getKey(), value);
+                            break;
                     }
+                } catch (Exception e)
+                {
+                    logger.catching(e);
+                    return getHTTPResponse(new ApiResponse("1", null,
+                            HTTPExceptions.INVALID_PARAMETERS.getCause(
+                                    e.getClass().getSimpleName(),
+                                    e.getMessage())));
                 }
-            } else
-            {
-                return getHTTPResponse(new ApiResponse("1", null,
-                        HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
             }
 
             ApiRequest apiRequest = new ApiRequest("1", method, methodParameters, sessionToken,
                     interactiveSessionKey, transactionManagerKey);
-            Response response =
-                    server.processOperation(apiRequest, apiResponseBuilder, performanceAuditor);
+            Response response = server.processOperation(apiRequest, apiResponseBuilder, performanceAuditor);
             HttpResponse httpResponse = getHTTPResponse(response);
             performanceAuditor.audit(Event.WriteResponse);
             logger.traceExit(performanceAuditor);
@@ -250,24 +217,24 @@ public class ApiServerAdapter<CONNECTION, API> implements HttpServerHandler
         return null; // This should never happen, it would mean an error writing the Unknown error happened.
     }
 
-    private <T> T readBody(byte[] requestBody, Class<T> valueType) throws Exception
-    {
-        return (T) jsonObjectMapper.readValue(new ByteArrayInputStream(requestBody), valueType);
-    }
-
-    private HttpResponse getHTTPResponse(Response response) throws Exception
+    public HttpResponse getHTTPResponse(Response response)
+            throws Exception
     {
         boolean error = response.getError() != null;
         String contentType = null;
         byte[] body = null;
-        if (response.getResult() instanceof byte[])
-        {
-            contentType = HttpResponse.CONTENT_TYPE_BINARY_DATA;
-            body = (byte[]) response.getResult();
-        } else
-        {
+        if (error) {
+            contentType = HttpResponse.CONTENT_TYPE_JSON;
+            body = jsonObjectMapper.writeValue(response);
+        } else if (response.getResult() instanceof List) {
             contentType = HttpResponse.CONTENT_TYPE_JSON;
             body = jsonObjectMapper.writeValue(response);
+        } else if(response.getResult() instanceof byte[]) {
+            contentType = HttpResponse.CONTENT_TYPE_BINARY_DATA;
+            body = (byte[]) response.getResult();
+        } else {
+            contentType = HttpResponse.CONTENT_TYPE_TEXT;
+            body = String.valueOf(response.getResult()).getBytes(StandardCharsets.UTF_8);
         }
         return new HttpResponse(error, contentType, body);
     }
diff --git a/server-data-store/src/main/java/ch/ethz/sis/afsserver/server/impl/ApiServerAdapterV2.java b/server-data-store/src/main/java/ch/ethz/sis/afsserver/server/impl/ApiServerAdapterV2.java
deleted file mode 100644
index 2b8806784208f9891f3c151b32206eb1f30deb85..0000000000000000000000000000000000000000
--- a/server-data-store/src/main/java/ch/ethz/sis/afsserver/server/impl/ApiServerAdapterV2.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright ETH 2022 - 2023 Zürich, Scientific IT Services
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ch.ethz.sis.afsserver.server.impl;
-
-import ch.ethz.sis.afsjson.JsonObjectMapper;
-import ch.ethz.sis.afsserver.exception.HTTPExceptions;
-import ch.ethz.sis.afsserver.http.HttpResponse;
-import ch.ethz.sis.afsserver.http.HttpServerHandler;
-import ch.ethz.sis.afsserver.server.APIServer;
-import ch.ethz.sis.afsserver.server.APIServerException;
-import ch.ethz.sis.afsserver.server.Request;
-import ch.ethz.sis.afsserver.server.Response;
-import ch.ethz.sis.afsserver.server.performance.Event;
-import ch.ethz.sis.afsserver.server.performance.PerformanceAuditor;
-import ch.ethz.sis.shared.log.LogManager;
-import ch.ethz.sis.shared.log.Logger;
-import io.netty.handler.codec.http.HttpMethod;
-
-import java.nio.charset.StandardCharsets;
-import java.util.*;
-
-import static io.netty.handler.codec.http.HttpMethod.*;
-
-/*
- * This class is supposed to be called by a TCP or HTTP transport class
- */
-public class ApiServerAdapterV2<CONNECTION, API> implements HttpServerHandler
-{
-
-    private static final Logger logger = LogManager.getLogger(ApiServerAdapterV2.class);
-
-    private final APIServer<CONNECTION, Request, Response, API> server;
-
-    private final JsonObjectMapper jsonObjectMapper;
-
-    private final ApiResponseBuilder apiResponseBuilder;
-
-    public ApiServerAdapterV2(
-            APIServer<CONNECTION, Request, Response, API> server,
-            JsonObjectMapper jsonObjectMapper)
-    {
-        this.server = server;
-        this.jsonObjectMapper = jsonObjectMapper;
-        this.apiResponseBuilder = new ApiResponseBuilder();
-    }
-
-    public static HttpMethod getHttpMethod(String apiMethod)
-    {
-        switch (apiMethod)
-        {
-            case "list":
-            case "read":
-            case "isSessionValid":
-                return GET; // all parameters from GET methods come on the query string
-            case "write":
-            case "move":
-            case "copy":
-            case "login":
-            case "logout":
-            case "begin":
-            case "prepare":
-            case "commit":
-            case "rollback":
-            case "recover":
-                return POST; // all parameters from POST methods come on the body
-            case "delete":
-                return HttpMethod.DELETE; // all parameters from DELETE methods come on the body
-        }
-        throw new UnsupportedOperationException("This line SHOULD NOT be unreachable!");
-    }
-
-    public boolean isValidMethod(HttpMethod givenMethod, String apiMethod)
-    {
-        HttpMethod correctMethod = getHttpMethod(apiMethod);
-        return correctMethod == givenMethod;
-    }
-
-    public HttpResponse process(HttpMethod httpMethod, Map<String, List<String>> parameters,
-            byte[] requestBody)
-    {
-        try
-        {
-            logger.traceAccess(null);
-            PerformanceAuditor performanceAuditor = new PerformanceAuditor();
-
-
-            if (httpMethod != GET && httpMethod != POST && httpMethod != DELETE)
-            {
-                return getHTTPResponse(new ApiResponse("1", null,
-                        HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
-            }
-
-            String method = null;
-            String sessionToken = null;
-            String interactiveSessionKey = null;
-            String transactionManagerKey = null;
-            Map<String, Object> methodParameters = new HashMap<>();
-
-            for (Map.Entry<String, List<String>> entry : parameters.entrySet())
-            {
-                String value = null;
-                if (entry.getValue() != null)
-                {
-                    if (entry.getValue().size() == 1)
-                    {
-                        value = entry.getValue().get(0);
-                    } else if (entry.getValue().size() > 1)
-                    {
-                        return getHTTPResponse(new ApiResponse("1", null,
-                                HTTPExceptions.INVALID_PARAMETERS.getCause()));
-                    }
-                }
-
-                try
-                {
-                    switch (entry.getKey())
-                    {
-                        case "method":
-                            method = value;
-                            if (!isValidMethod(httpMethod, method))
-                            {
-                                return getHTTPResponse(new ApiResponse("1", null,
-                                        HTTPExceptions.INVALID_HTTP_METHOD.getCause()));
-                            }
-                            break;
-                        case "sessionToken":
-                            sessionToken = value;
-                            break;
-                        case "interactiveSessionKey":
-                            interactiveSessionKey = value;
-                            break;
-                        case "transactionManagerKey":
-                            transactionManagerKey = value;
-                            break;
-                        case "transactionId":
-                            methodParameters.put(entry.getKey(), UUID.fromString(value));
-                            break;
-                        case "recursively":
-                            methodParameters.put(entry.getKey(), Boolean.valueOf(value));
-                            break;
-                        case "offset":
-                            methodParameters.put(entry.getKey(), Long.valueOf(value));
-                            break;
-                        case "limit":
-                            methodParameters.put(entry.getKey(), Integer.valueOf(value));
-                            break;
-                        case "data":
-                            methodParameters.put(entry.getKey(), Base64.getDecoder().decode(value));
-                            break;
-                        case "md5Hash":
-                            methodParameters.put(entry.getKey(), Base64.getDecoder().decode(value));
-                            break;
-                        default:
-                            methodParameters.put(entry.getKey(), value);
-                            break;
-                    }
-                } catch (Exception e)
-                {
-                    logger.catching(e);
-                    return getHTTPResponse(new ApiResponse("1", null,
-                            HTTPExceptions.INVALID_PARAMETERS.getCause(
-                                    e.getClass().getSimpleName(),
-                                    e.getMessage())));
-                }
-            }
-
-            ApiRequest apiRequest = new ApiRequest("1", method, methodParameters, sessionToken,
-                    interactiveSessionKey, transactionManagerKey);
-            Response response = server.processOperation(apiRequest, apiResponseBuilder, performanceAuditor);
-            HttpResponse httpResponse = getHTTPResponse(response);
-            performanceAuditor.audit(Event.WriteResponse);
-            logger.traceExit(performanceAuditor);
-            logger.traceExit(httpResponse);
-            return httpResponse;
-        } catch (APIServerException e)
-        {
-            logger.catching(e);
-            switch (e.getType())
-            {
-                case MethodNotFound:
-                case IncorrectParameters:
-                case InternalError:
-                    try
-                    {
-                        return getHTTPResponse(new ApiResponse("1", null, e.getData()));
-                    } catch (Exception ex)
-                    {
-                        logger.catching(ex);
-                    }
-            }
-        } catch (Exception e)
-        {
-            logger.catching(e);
-            try
-            {
-                return getHTTPResponse(new ApiResponse("1", null,
-                        HTTPExceptions.UNKNOWN.getCause(e.getClass().getSimpleName(),
-                                e.getMessage())));
-            } catch (Exception ex)
-            {
-                logger.catching(ex);
-            }
-        }
-        return null; // This should never happen, it would mean an error writing the Unknown error happened.
-    }
-
-    public HttpResponse getHTTPResponse(Response response)
-            throws Exception
-    {
-        boolean error = response.getError() != null;
-        String contentType = null;
-        byte[] body = null;
-        if (response.getResult() instanceof List) {
-            contentType = HttpResponse.CONTENT_TYPE_JSON;
-            body = jsonObjectMapper.writeValue(response);
-        } else if(response.getResult() instanceof byte[]) {
-            contentType = HttpResponse.CONTENT_TYPE_BINARY_DATA;
-            body = (byte[]) response.getResult();
-        } else {
-            contentType = HttpResponse.CONTENT_TYPE_TEXT;
-            body = String.valueOf(response.getResult()).getBytes(StandardCharsets.UTF_8);
-        }
-        return new HttpResponse(error, contentType, body);
-    }
-
-}
\ No newline at end of file
diff --git a/server-data-store/src/test/java/ch/ethz/sis/afsserver/core/AbstractPublicAPIWrapper.java b/server-data-store/src/test/java/ch/ethz/sis/afsserver/core/AbstractPublicAPIWrapper.java
index 27853db9e03455cbcc08c4b228ce21dbad4198af..6695bc3aeeddca9b0a40e7bdf06f0eb11a4babda 100644
--- a/server-data-store/src/test/java/ch/ethz/sis/afsserver/core/AbstractPublicAPIWrapper.java
+++ b/server-data-store/src/test/java/ch/ethz/sis/afsserver/core/AbstractPublicAPIWrapper.java
@@ -15,13 +15,10 @@
  */
 package ch.ethz.sis.afsserver.core;
 
-import ch.ethz.sis.afsapi.dto.File;
 import ch.ethz.sis.afsapi.api.PublicAPI;
+import ch.ethz.sis.afsapi.dto.File;
 import lombok.NonNull;
 
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -29,8 +26,7 @@ import java.util.UUID;
 public abstract class AbstractPublicAPIWrapper implements PublicAPI
 {
 
-    public abstract <E> E process(String method, Map<String, Object> queryParams,
-            Map<String, Object> bodyParams);
+    public abstract <E> E process(Class<E> responseType, String method, Map<String, Object> params);
 
     @Override
     public List<File> list(@NonNull String owner, @NonNull String source,
@@ -40,7 +36,7 @@ public abstract class AbstractPublicAPIWrapper implements PublicAPI
                 "owner", owner,
                 "source", source,
                 "recursively", recursively);
-        return process("list", args, Map.of());
+        return process(List.class, "list", args);
     }
 
     @Override
@@ -52,7 +48,7 @@ public abstract class AbstractPublicAPIWrapper implements PublicAPI
                 "source", source,
                 "offset", offset,
                 "limit", limit);
-        return process("read", args, Map.of());
+        return process(byte[].class,"read", args);
     }
 
     @Override
@@ -65,7 +61,7 @@ public abstract class AbstractPublicAPIWrapper implements PublicAPI
                 "offset", offset,
                 "data", data,
                 "md5Hash", md5Hash);
-        return process("write", Map.of(), args);
+        return process(Boolean.class, "write", args);
     }
 
     @Override
@@ -74,7 +70,7 @@ public abstract class AbstractPublicAPIWrapper implements PublicAPI
         Map<String, Object> args = Map.of(
                 "owner", owner,
                 "source", source);
-        return process("delete", Map.of(), args);
+        return process(Boolean.class, "delete", args);
     }
 
     @Override
@@ -86,7 +82,7 @@ public abstract class AbstractPublicAPIWrapper implements PublicAPI
                 "source", source,
                 "targetOwner", targetOwner,
                 "target", target);
-        return process("copy", Map.of(), args);
+        return process(Boolean.class,"copy", args);
     }
 
     @Override
@@ -98,7 +94,7 @@ public abstract class AbstractPublicAPIWrapper implements PublicAPI
                 "source", source,
                 "targetOwner", targetOwner,
                 "target", target);
-        return process("move", Map.of(), args);
+        return process(Boolean.class, "move", args);
     }
 
     @Override
diff --git a/server-data-store/src/test/java/ch/ethz/sis/afsserver/core/AbstractPublicAPIWrapperV2.java b/server-data-store/src/test/java/ch/ethz/sis/afsserver/core/AbstractPublicAPIWrapperV2.java
deleted file mode 100644
index 661e8a2258ae02b7c290a9765617f992aaab4b26..0000000000000000000000000000000000000000
--- a/server-data-store/src/test/java/ch/ethz/sis/afsserver/core/AbstractPublicAPIWrapperV2.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright ETH 2022 - 2023 Zürich, Scientific IT Services
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ch.ethz.sis.afsserver.core;
-
-import ch.ethz.sis.afsapi.api.PublicAPI;
-import ch.ethz.sis.afsapi.dto.File;
-import lombok.NonNull;
-
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-public abstract class AbstractPublicAPIWrapperV2 implements PublicAPI
-{
-
-    public abstract <E> E process(Class<E> responseType, String method, Map<String, Object> params);
-
-    @Override
-    public List<File> list(@NonNull String owner, @NonNull String source,
-            @NonNull Boolean recursively) throws Exception
-    {
-        Map<String, Object> args = Map.of(
-                "owner", owner,
-                "source", source,
-                "recursively", recursively);
-        return process(List.class, "list", args);
-    }
-
-    @Override
-    public byte[] read(@NonNull String owner, @NonNull String source, @NonNull Long offset,
-            @NonNull Integer limit) throws Exception
-    {
-        Map<String, Object> args = Map.of(
-                "owner", owner,
-                "source", source,
-                "offset", offset,
-                "limit", limit);
-        return process(byte[].class,"read", args);
-    }
-
-    @Override
-    public Boolean write(@NonNull String owner, @NonNull String source, @NonNull Long offset,
-            @NonNull byte[] data, @NonNull byte[] md5Hash) throws Exception
-    {
-        Map<String, Object> args = Map.of(
-                "owner", owner,
-                "source", source,
-                "offset", offset,
-                "data", data,
-                "md5Hash", md5Hash);
-        return process(Boolean.class, "write", args);
-    }
-
-    @Override
-    public Boolean delete(@NonNull String owner, @NonNull String source) throws Exception
-    {
-        Map<String, Object> args = Map.of(
-                "owner", owner,
-                "source", source);
-        return process(Boolean.class, "delete", args);
-    }
-
-    @Override
-    public Boolean copy(@NonNull String sourceOwner, @NonNull String source,
-            @NonNull String targetOwner, @NonNull String target) throws Exception
-    {
-        Map<String, Object> args = Map.of(
-                "sourceOwner", sourceOwner,
-                "source", source,
-                "targetOwner", targetOwner,
-                "target", target);
-        return process(Boolean.class,"copy", args);
-    }
-
-    @Override
-    public Boolean move(@NonNull String sourceOwner, @NonNull String source,
-            @NonNull String targetOwner, @NonNull String target) throws Exception
-    {
-        Map<String, Object> args = Map.of(
-                "sourceOwner", sourceOwner,
-                "source", source,
-                "targetOwner", targetOwner,
-                "target", target);
-        return process(Boolean.class, "move", args);
-    }
-
-    @Override
-    public void begin(UUID transactionId) throws Exception
-    {
-        //TODO: Unused
-    }
-
-    @Override
-    public Boolean prepare() throws Exception
-    {
-        //TODO: Unused
-        return true;
-    }
-
-    @Override
-    public void commit() throws Exception
-    {
-        //TODO: Unused
-    }
-
-    @Override
-    public void rollback() throws Exception
-    {
-        //TODO: Unused
-    }
-
-    @Override
-    public List<UUID> recover() throws Exception
-    {
-        //TODO: Unused
-        return null;
-    }
-
-    @Override
-    public String login(String userId, String password) throws Exception
-    {
-        //TODO: Unused
-        return null;
-    }
-
-    @Override
-    public Boolean isSessionValid() throws Exception
-    {
-        //TODO: Unused
-        return null;
-    }
-
-    @Override
-    public Boolean logout() throws Exception
-    {
-        //TODO: Unused
-        return null;
-    }
-}
diff --git a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerAdapterWrapper.java b/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerAdapterWrapper.java
index b4fbd223a434ddb7172f7815edddfd79a91456eb..91972ae76949d1abb0a8dfcb27016aa78831e5eb 100644
--- a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerAdapterWrapper.java
+++ b/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerAdapterWrapper.java
@@ -15,24 +15,19 @@
  */
 package ch.ethz.sis.afsserver.impl;
 
+import ch.ethz.sis.afsclient.client.AfsClient;
 import ch.ethz.sis.afsserver.core.AbstractPublicAPIWrapper;
 import ch.ethz.sis.afsserver.http.HttpResponse;
-import ch.ethz.sis.afsserver.server.impl.ApiRequest;
-import ch.ethz.sis.afsserver.server.impl.ApiResponse;
 import ch.ethz.sis.afsserver.server.impl.ApiServerAdapter;
-import ch.ethz.sis.afsserver.server.performance.PerformanceAuditor;
 import ch.ethz.sis.shared.io.IOUtils;
-import ch.ethz.sis.afsjson.JsonObjectMapper;
 import ch.ethz.sis.shared.log.LogManager;
 import ch.ethz.sis.shared.log.Logger;
 import io.netty.handler.codec.http.HttpMethod;
 
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.*;
-
-import static ch.ethz.sis.afsserver.http.HttpResponse.CONTENT_TYPE_BINARY_DATA;
-import static ch.ethz.sis.afsserver.http.HttpResponse.CONTENT_TYPE_JSON;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
 
 public class APIServerAdapterWrapper extends AbstractPublicAPIWrapper
 {
@@ -41,13 +36,10 @@ public class APIServerAdapterWrapper extends AbstractPublicAPIWrapper
 
     private ApiServerAdapter apiServerAdapter;
 
-    private JsonObjectMapper jsonObjectMapper;
 
-    public APIServerAdapterWrapper(ApiServerAdapter apiServerAdapter,
-            JsonObjectMapper jsonObjectMapper)
+    public APIServerAdapterWrapper(ApiServerAdapter apiServerAdapter)
     {
         this.apiServerAdapter = apiServerAdapter;
-        this.jsonObjectMapper = jsonObjectMapper;
     }
 
     public Map<String, List<String>> getURIParameters(Map<String, Object> args)
@@ -55,13 +47,9 @@ public class APIServerAdapterWrapper extends AbstractPublicAPIWrapper
         Map<String, List<String>> result = new HashMap<>(args.size());
         for (Map.Entry<String, Object> entry : args.entrySet())
         {
-            if (entry.getKey().equals("data") && entry.getValue() instanceof byte[])
-            {
-                continue; // Skip
-            } else if (entry.getValue() instanceof byte[])
+            if (entry.getValue() instanceof byte[])
             {
-                result.put(entry.getKey(),
-                        List.of(IOUtils.encodeBase64((byte[]) entry.getValue())));
+                result.put(entry.getKey(), List.of(IOUtils.encodeBase64((byte[]) entry.getValue())));
             } else
             {
                 result.put(entry.getKey(), List.of(String.valueOf(entry.getValue())));
@@ -70,49 +58,39 @@ public class APIServerAdapterWrapper extends AbstractPublicAPIWrapper
         return result;
     }
 
-    public <E> E process(String apiMethod, Map<String, Object> queryParams,
-            Map<String, Object> bodyParams)
+    public <E> E process(Class<E> responseType, String apiMethod, Map<String, Object> params)
     {
         try
         {
             HttpMethod httpMethod = ApiServerAdapter.getHttpMethod(apiMethod);
-            Map<String, List<String>> uriParameters = new HashMap<>();
+            Map<String, List<String>> requestParameters = getURIParameters(params);
+            requestParameters.put("sessionToken", List.of(UUID.randomUUID().toString()));
+            requestParameters.put("method", List.of(apiMethod));
+
             byte[] requestBody = null;
 
             if (HttpMethod.GET.equals(httpMethod))
             {
-                uriParameters = getURIParameters(queryParams);
-                uriParameters.put("sessionToken", List.of(UUID.randomUUID().toString()));
+                // Do nothing
             } else if (HttpMethod.POST.equals(httpMethod) || HttpMethod.DELETE.equals(httpMethod))
             {
-                Map<String, Object> fullBodyParams = new HashMap<>();
-                fullBodyParams.putAll(bodyParams);
-                fullBodyParams.put("sessionToken", UUID.randomUUID().toString());
-                requestBody = jsonObjectMapper.writeValue(fullBodyParams);
+                // Do nothing
             } else
             {
                 throw new IllegalArgumentException("Not supported HTTP method type!");
             }
 
-            uriParameters.put("method", List.of(apiMethod));
 
-            HttpResponse response =
-                    apiServerAdapter.process(httpMethod, uriParameters, requestBody);
-            switch (response.getContentType())
-            {
-                case CONTENT_TYPE_BINARY_DATA:
-                    return (E) response.getBody();
-                case CONTENT_TYPE_JSON:
-                    ApiResponse apiResponse =
-                            jsonObjectMapper.readValue(new ByteArrayInputStream(response.getBody()),
-                                    ApiResponse.class);
-                    return (E) apiResponse.getResult();
-            }
+
+            HttpResponse response = apiServerAdapter.process(httpMethod, requestParameters, null);
+            String contentType = response.getContentType();
+            byte[] body = response.getBody();
+
+            return AfsClient.getResponseResult(responseType, contentType, body);
         } catch (Throwable throwable)
         {
             throw new RuntimeException(throwable);
         }
-        throw new RuntimeException("This line should be unreachable");
     }
 
 }
diff --git a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerAdapterWrapperV2.java b/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerAdapterWrapperV2.java
deleted file mode 100644
index 810d8460872b687d1ddf45997e3d369c2c7e9f03..0000000000000000000000000000000000000000
--- a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerAdapterWrapperV2.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright ETH 2022 - 2023 Zürich, Scientific IT Services
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ch.ethz.sis.afsserver.impl;
-
-import ch.ethz.sis.afsclient.client.AfsClientV2;
-import ch.ethz.sis.afsserver.core.AbstractPublicAPIWrapperV2;
-import ch.ethz.sis.afsserver.http.HttpResponse;
-import ch.ethz.sis.afsserver.server.impl.ApiServerAdapter;
-import ch.ethz.sis.shared.io.IOUtils;
-import ch.ethz.sis.shared.log.LogManager;
-import ch.ethz.sis.shared.log.Logger;
-import io.netty.handler.codec.http.HttpMethod;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-public class APIServerAdapterWrapperV2 extends AbstractPublicAPIWrapperV2
-{
-
-    private static final Logger logger = LogManager.getLogger(APIServerAdapterWrapperV2.class);
-
-    private ApiServerAdapter apiServerAdapter;
-
-
-    public APIServerAdapterWrapperV2(ApiServerAdapter apiServerAdapter)
-    {
-        this.apiServerAdapter = apiServerAdapter;
-    }
-
-    public Map<String, List<String>> getURIParameters(Map<String, Object> args)
-    {
-        Map<String, List<String>> result = new HashMap<>(args.size());
-        for (Map.Entry<String, Object> entry : args.entrySet())
-        {
-            if (entry.getValue() instanceof byte[])
-            {
-                result.put(entry.getKey(), List.of(IOUtils.encodeBase64((byte[]) entry.getValue())));
-            } else
-            {
-                result.put(entry.getKey(), List.of(String.valueOf(entry.getValue())));
-            }
-        }
-        return result;
-    }
-
-    public <E> E process(Class<E> responseType, String apiMethod, Map<String, Object> params)
-    {
-        try
-        {
-            HttpMethod httpMethod = ApiServerAdapter.getHttpMethod(apiMethod);
-            Map<String, List<String>> requestParameters = getURIParameters(params);
-            requestParameters.put("sessionToken", List.of(UUID.randomUUID().toString()));
-            requestParameters.put("method", List.of(apiMethod));
-
-            byte[] requestBody = null;
-
-            if (HttpMethod.GET.equals(httpMethod))
-            {
-                // Do nothing
-            } else if (HttpMethod.POST.equals(httpMethod) || HttpMethod.DELETE.equals(httpMethod))
-            {
-                // Do nothing
-            } else
-            {
-                throw new IllegalArgumentException("Not supported HTTP method type!");
-            }
-
-
-
-            HttpResponse response = apiServerAdapter.process(httpMethod, requestParameters, null);
-            String contentType = response.getContentType();
-            byte[] body = response.getBody();
-
-            return AfsClientV2.getResponseResult(responseType, contentType, body);
-        } catch (Throwable throwable)
-        {
-            throw new RuntimeException(throwable);
-        }
-    }
-
-}
diff --git a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerWrapper.java b/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerWrapper.java
index 4f0b7cbc308313a33c831180947f03111cfeeedb..4746825aef72aa1c7de900bacc3b24f90eb7cf5a 100644
--- a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerWrapper.java
+++ b/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerWrapper.java
@@ -25,11 +25,11 @@ import ch.ethz.sis.afsserver.server.performance.PerformanceAuditor;
 import ch.ethz.sis.shared.log.LogManager;
 import ch.ethz.sis.shared.log.Logger;
 
-import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
 
-public class APIServerWrapper extends AbstractPublicAPIWrapper {
+public class APIServerWrapper extends AbstractPublicAPIWrapper
+{
 
     private static final Logger logger = LogManager.getLogger(APIServerWrapper.class);
 
@@ -41,13 +41,10 @@ public class APIServerWrapper extends AbstractPublicAPIWrapper {
         this.apiResponseBuilder = new ApiResponseBuilder();
     }
 
-    public <E> E process(String method, Map<String, Object> queryParams, Map<String, Object> bodyParams) {
+    public <E> E process(Class<E> responseType, String method, Map<String, Object> params) {
         PerformanceAuditor performanceAuditor = new PerformanceAuditor();
         // Random Session token just works for tests with dummy authentication
-        Map<String, Object> args = new HashMap<>();
-        args.putAll(queryParams);
-        args.putAll(bodyParams);
-        ApiRequest request = new ApiRequest("test", method, args, UUID.randomUUID().toString(), null, null);
+        ApiRequest request = new ApiRequest("test", method, params, UUID.randomUUID().toString(), null, null);
 
         try {
             Response response = apiServer.processOperation(request, apiResponseBuilder, performanceAuditor);
diff --git a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerWrapperV2.java b/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerWrapperV2.java
deleted file mode 100644
index 6384b1ed15c5df46478c54964aebc0d37534c411..0000000000000000000000000000000000000000
--- a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/APIServerWrapperV2.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright ETH 2022 - 2023 Zürich, Scientific IT Services
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ch.ethz.sis.afsserver.impl;
-
-
-import ch.ethz.sis.afsserver.core.AbstractPublicAPIWrapperV2;
-import ch.ethz.sis.afsserver.server.APIServer;
-import ch.ethz.sis.afsserver.server.Response;
-import ch.ethz.sis.afsserver.server.impl.ApiRequest;
-import ch.ethz.sis.afsserver.server.impl.ApiResponseBuilder;
-import ch.ethz.sis.afsserver.server.performance.PerformanceAuditor;
-import ch.ethz.sis.shared.log.LogManager;
-import ch.ethz.sis.shared.log.Logger;
-
-import java.util.Map;
-import java.util.UUID;
-
-public class APIServerWrapperV2 extends AbstractPublicAPIWrapperV2
-{
-
-    private static final Logger logger = LogManager.getLogger(APIServerWrapperV2.class);
-
-    private APIServer apiServer;
-    private final ApiResponseBuilder apiResponseBuilder;
-
-    public APIServerWrapperV2(APIServer apiServer) {
-        this.apiServer = apiServer;
-        this.apiResponseBuilder = new ApiResponseBuilder();
-    }
-
-    public <E> E process(Class<E> responseType, String method, Map<String, Object> params) {
-        PerformanceAuditor performanceAuditor = new PerformanceAuditor();
-        // Random Session token just works for tests with dummy authentication
-        ApiRequest request = new ApiRequest("test", method, params, UUID.randomUUID().toString(), null, null);
-
-        try {
-            Response response = apiServer.processOperation(request, apiResponseBuilder, performanceAuditor);
-            return (E) response.getResult();
-        } catch (Throwable throwable) {
-            throw new RuntimeException(throwable);
-        }
-    }
-
-}
diff --git a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/ApiServerAdapterTest.java b/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/ApiServerAdapterTest.java
index e61913bf65df3447b73cb0669d68c9a09234f642..711a8bda4451a14f6b9b01081b829c5d352fb06a 100644
--- a/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/ApiServerAdapterTest.java
+++ b/server-data-store/src/test/java/ch/ethz/sis/afsserver/impl/ApiServerAdapterTest.java
@@ -31,6 +31,6 @@ public class ApiServerAdapterTest extends ApiServerTest {
         Configuration configuration = ServerClientEnvironmentFS.getInstance().getDefaultServerConfiguration();
         JsonObjectMapper jsonObjectMapper = configuration.getSharableInstance(AtomicFileSystemServerParameter.jsonObjectMapperClass);
         ApiServerAdapter apiServerAdapter = new ApiServerAdapter(apiServer, jsonObjectMapper);
-        return new APIServerAdapterWrapper(apiServerAdapter, jsonObjectMapper);
+        return new APIServerAdapterWrapper(apiServerAdapter);
     }
 }