diff --git a/AbstractusAPI/src/main/java/AbstractusAPI/exception/AbstractusException.java b/AbstractusAPI/src/main/java/AbstractusAPI/exception/AbstractusException.java
index b3273b3..3da0bf7 100644
--- a/AbstractusAPI/src/main/java/AbstractusAPI/exception/AbstractusException.java
+++ b/AbstractusAPI/src/main/java/AbstractusAPI/exception/AbstractusException.java
@@ -10,6 +10,7 @@ public class AbstractusException extends RuntimeException {
 
     private final int errorCode;
 
+
     public AbstractusException(String message, int errorCode) {
         this.message = message;
         this.errorCode = errorCode;
diff --git a/AbstractusAPI/src/main/java/AbstractusAPI/http/query/Endpoint.java b/AbstractusAPI/src/main/java/AbstractusAPI/http/query/Endpoint.java
new file mode 100644
index 0000000..d7d6f83
--- /dev/null
+++ b/AbstractusAPI/src/main/java/AbstractusAPI/http/query/Endpoint.java
@@ -0,0 +1,8 @@
+package AbstractusAPI.http.query;
+
+public record Endpoint(String... path) {
+
+    public String getPath() {
+        return "/" + String.join("/", path);
+    }
+}
diff --git a/AbstractusAPI/src/main/java/AbstractusAPI/http/request/BasicRequestValidator.java b/AbstractusAPI/src/main/java/AbstractusAPI/http/request/BasicRequestValidator.java
index 3f05dd1..8a04edd 100644
--- a/AbstractusAPI/src/main/java/AbstractusAPI/http/request/BasicRequestValidator.java
+++ b/AbstractusAPI/src/main/java/AbstractusAPI/http/request/BasicRequestValidator.java
@@ -1,77 +1,94 @@
 package AbstractusAPI.http.request;
 
+import AbstractusAPI.exception.AbstractusException;
 import AbstractusAPI.exception.client_error.*;
 import AbstractusAPI.exception.server_error.*;
-import AbstractusAPI.exception.server_error.HTTPVersionNotSupportedException;
 
 import okhttp3.Response;
 import org.json.JSONObject;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Basic implementation of {@link RequestValidator}. Handles most
  * status codes that can be returned from an API.
  */
 public class BasicRequestValidator implements RequestValidator {
 
+    private static final Map<Integer, Class<? extends AbstractusException>> CLIENT_ERROR_MAP = new HashMap<>();
+    private static final Map<Integer, Class<? extends AbstractusException>> SERVER_ERROR_MAP = new HashMap<>();
+
+    static {
+        // Client error mappings
+        CLIENT_ERROR_MAP.put(400, BadRequestException.class);
+        CLIENT_ERROR_MAP.put(401, UnauthorizedException.class);
+        CLIENT_ERROR_MAP.put(402, PaymentRequiredException.class);
+        CLIENT_ERROR_MAP.put(403, ForbiddenException.class);
+        CLIENT_ERROR_MAP.put(404, NotFoundException.class);
+        CLIENT_ERROR_MAP.put(405, MethodNotAllowedException.class);
+        CLIENT_ERROR_MAP.put(406, NotAcceptableException.class);
+        CLIENT_ERROR_MAP.put(407, ProxyAuthenticationRequiredException.class);
+        CLIENT_ERROR_MAP.put(408, RequestTimeoutException.class);
+        CLIENT_ERROR_MAP.put(409, ConflictException.class);
+        CLIENT_ERROR_MAP.put(410, GoneException.class);
+        CLIENT_ERROR_MAP.put(411, LengthRequiredException.class);
+        CLIENT_ERROR_MAP.put(412, PreconditionFailedException.class);
+        CLIENT_ERROR_MAP.put(413, PayloadTooLargeException.class);
+        CLIENT_ERROR_MAP.put(414, URITooLongException.class);
+        CLIENT_ERROR_MAP.put(415, UnsupportedMediaTypeException.class);
+        CLIENT_ERROR_MAP.put(416, RangeNotSatisfiableException.class);
+        CLIENT_ERROR_MAP.put(417, ExpectationFailedException.class);
+        CLIENT_ERROR_MAP.put(418, TeapotException.class);
+        CLIENT_ERROR_MAP.put(419, MisdirectedRequestException.class);
+        CLIENT_ERROR_MAP.put(422, UnprocessableEntityException.class);
+        CLIENT_ERROR_MAP.put(423, LockedException.class);
+        CLIENT_ERROR_MAP.put(424, FailedDependencyException.class);
+        CLIENT_ERROR_MAP.put(425, TooEarlyException.class);
+        CLIENT_ERROR_MAP.put(426, UpgradeRequiredException.class);
+        CLIENT_ERROR_MAP.put(428, PreconditionRequiredException.class);
+        CLIENT_ERROR_MAP.put(429, RateLimitingException.class);
+        CLIENT_ERROR_MAP.put(431, RequestHeaderFieldsTooLargeException.class);
+        CLIENT_ERROR_MAP.put(451, UnavailableForLegalReasonsException.class);
+
+        // Server error mappings
+        SERVER_ERROR_MAP.put(500, InternalServerErrorException.class);
+        SERVER_ERROR_MAP.put(501, NotImplementedException.class);
+        SERVER_ERROR_MAP.put(502, BadGatewayException.class);
+        SERVER_ERROR_MAP.put(503, ServiceUnavailableException.class);
+        SERVER_ERROR_MAP.put(504, GatewayTimeoutException.class);
+        SERVER_ERROR_MAP.put(505, HTTPVersionNotSupportedException.class);
+        SERVER_ERROR_MAP.put(506, VariantAlsoNegotiatesException.class);
+        SERVER_ERROR_MAP.put(507, InsufficientStorageException.class);
+        SERVER_ERROR_MAP.put(508, LoopDetectedException.class);
+        SERVER_ERROR_MAP.put(510, NotExtendedException.class);
+        SERVER_ERROR_MAP.put(511, NetworkAuthenticationException.class);
+    }
 
     @Override
     public boolean validate(Response response, JSONObject returnObject) {
         if (response.isSuccessful()) {
             return true;
         } else {
-            String failString = returnObject.getString("cause");
-
-            switch (response.code()) {
+            String failString = returnObject.optString("cause", "Unknown error");
+            int statusCode = response.code();
 
-                // client errors
-                case 400 -> throw new BadRequestException(failString);
-                case 401 -> throw new UnauthorizedException(failString);
-                case 402 -> throw new PaymentRequiredException(failString);
-                case 403 -> throw new ForbiddenException(failString);
-                case 404 -> throw new NotFoundException(failString);
-                case 405 -> throw new MethodNotAllowedException(failString);
-                case 406 -> throw new NotAcceptableException(failString);
-                case 407 -> throw new ProxyAuthenticationRequiredException(failString);
-                case 408 -> throw new RequestTimeoutException(failString);
-                case 409 -> throw new ConflictException(failString);
-                case 410 -> throw new GoneException(failString);
-                case 411 -> throw new LengthRequiredException(failString);
-                case 412 -> throw new PreconditionFailedException(failString);
-                case 413 -> throw new PayloadTooLargeException(failString);
-                case 414 -> throw new URITooLongException(failString);
-                case 415 -> throw new UnsupportedMediaTypeException(failString);
-                case 416 -> throw new RangeNotSatisfiableException(failString);
-                case 417 -> throw new ExpectationFailedException(failString);
-                case 418 -> throw new TeapotException(failString);
-                case 419 -> throw new MisdirectedRequestException(failString);
-                case 422 -> throw new UnprocessableEntityException(failString);
-                case 423 -> throw new LockedException(failString);
-                case 424 -> throw new FailedDependencyException(failString);
-                case 425 -> throw new TooEarlyException(failString);
-                case 426 -> throw new UpgradeRequiredException(failString);
-                case 428 -> throw new PreconditionRequiredException(failString);
-                case 429 -> throw new RateLimitingException(failString);
-                case 431 -> throw new RequestHeaderFieldsTooLargeException(failString);
-                case 451 -> throw new UnavailableForLegalReasonsException(failString);
-
-                // server errors
-                case 500 -> throw new InternalServerErrorException(failString);
-                case 501 -> throw new NotImplementedException(failString);
-                case 502 -> throw new BadGatewayException(failString);
-                case 503 -> throw new ServiceUnavailableException(failString);
-                case 504 -> throw new GatewayTimeoutException(failString);
-                case 505 -> throw new HTTPVersionNotSupportedException(failString);
-                case 506 -> throw new VariantAlsoNegotiatesException(failString);
-                case 507 -> throw new InsufficientStorageException(failString);
-                case 508 -> throw new LoopDetectedException(failString);
-                case 510 -> throw new NotExtendedException(failString);
-                case 511 -> throw new NetworkAuthenticationException(failString);
-
-                default -> {
-                    return false;
-                }
+            if (CLIENT_ERROR_MAP.containsKey(statusCode)) {
+                throwException(CLIENT_ERROR_MAP.get(statusCode), failString);
+            } else if (SERVER_ERROR_MAP.containsKey(statusCode)) {
+                throwException(SERVER_ERROR_MAP.get(statusCode), failString);
+            } else {
+                return false;
+            }
+        }
+        return false;
+    }
 
+        private void throwException (Class <? extends AbstractusException> exceptionClass, String message){
+            try {
+                throw exceptionClass.getConstructor(String.class).newInstance(message);
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException("Failed to instantiate exception for status code", e);
             }
         }
     }
-}
diff --git a/AbstractusAPI/src/main/java/AbstractusAPI/http/request/RequestController.java b/AbstractusAPI/src/main/java/AbstractusAPI/http/request/RequestController.java
index 7df2979..97aa0d1 100644
--- a/AbstractusAPI/src/main/java/AbstractusAPI/http/request/RequestController.java
+++ b/AbstractusAPI/src/main/java/AbstractusAPI/http/request/RequestController.java
@@ -1,5 +1,6 @@
 package AbstractusAPI.http.request;
 
+import AbstractusAPI.http.query.Endpoint;
 import AbstractusAPI.http.query.Query;
 import AbstractusAPI.http.query.QueryParameter;
 import okhttp3.OkHttpClient;
@@ -22,6 +23,7 @@ public class RequestController {
     private final String hostname;
     private final RequestFactory requestFactory;
 
+
     public RequestController(String origin, String hostname) {
         this.origin = origin;
         this.hostname = hostname;
@@ -46,24 +48,57 @@ public RequestController(String origin, String hostname, OkHttpClient client, Re
         this.requestFactory = new RequestFactory(client, validator);
     }
 
+    public void setAutoClearCache(boolean autoClear) {
+        requestFactory.setAutoClearCache(autoClear);
+    }
+
+    public CompletableFuture<JSONObject> sendRequestAsync() {
+        try {
+            URL url = new URL(origin, hostname, "/");
+            Query query = new Query(url);
+            query.addParameter(queryParameters.toArray(new QueryParameter[0]));
+            return requestFactory.sendAsync(query);
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
 
-    public CompletableFuture<JSONObject> sendRequestAsync(String endpoint, QueryParameter... params) {
+    public CompletableFuture<JSONObject> sendRequestAsync(QueryParameter... params) {
         try {
-            URL url = new URL(origin, hostname, "/" + endpoint);
+            URL url = new URL(origin, hostname, "/");
             Query query = new Query(url);
             query.addParameter(params);
-            query.addParameter(queryParameters.toArray(new QueryParameter[queryParameters.size()]));
+            query.addParameter(queryParameters.toArray(new QueryParameter[0]));
+            return requestFactory.sendAsync(query);
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    public CompletableFuture<JSONObject> sendRequestAsync(Endpoint endpoint, QueryParameter... params) {
+        try {
+
+            // Create the URL object
+            URL url = new URL(origin, hostname, endpoint.getPath());
+
+            // Create and configure the Query object
+            Query query = new Query(url);
+            query.addParameter(params);
+            query.addParameter(queryParameters.toArray(new QueryParameter[0]));
+
+            // Send the request asynchronously
             return requestFactory.sendAsync(query);
         } catch (MalformedURLException e) {
             throw new RuntimeException(e);
         }
     }
 
-    public CompletableFuture<JSONObject> sendRequestAsync(String endpoint) {
+    public CompletableFuture<JSONObject> sendRequestAsync(Endpoint endpoint) {
         try {
-            URL url = new URL(origin, hostname, "/" + endpoint);
+            URL url = new URL(origin, hostname, endpoint.getPath());
             Query query = new Query(url);
-            query.addParameter(queryParameters.toArray(new QueryParameter[queryParameters.size()]));
+            query.addParameter(queryParameters.toArray(new QueryParameter[0]));
             return requestFactory.sendAsync(query);
         } catch (MalformedURLException e) {
             throw new RuntimeException(e);
@@ -75,18 +110,18 @@ public void clearCache() {
     }
 
     public void setApiKey(UUID apiKey) {
-        addPermanentQueryParameter(new QueryParameter("key", apiKey.toString()));
+        addQueryParameter(new QueryParameter("key", apiKey.toString()));
     }
 
     /**
      * Adds a parameter to every request being made.
      * @param parameter The parameter to add.
      */
-    public void addPermanentQueryParameter(QueryParameter parameter) {
+    public void addQueryParameter(QueryParameter parameter) {
         queryParameters.add(parameter);
     }
 
-    public void removePermanentQueryParameter(QueryParameter parameter) {
+    public void removeQueryParameter(QueryParameter parameter) {
         queryParameters.remove(parameter);
     }
 }
diff --git a/AbstractusAPI/src/main/java/AbstractusAPI/http/request/RequestFactory.java b/AbstractusAPI/src/main/java/AbstractusAPI/http/request/RequestFactory.java
index 4351c5d..6f3fabc 100644
--- a/AbstractusAPI/src/main/java/AbstractusAPI/http/request/RequestFactory.java
+++ b/AbstractusAPI/src/main/java/AbstractusAPI/http/request/RequestFactory.java
@@ -20,6 +20,7 @@ public class RequestFactory {
 
     private final OkHttpClient client;
     private final RequestValidator validator;
+    private boolean autoClearCache;
 
     protected RequestFactory() {
         this.validator = new BasicRequestValidator();
@@ -41,6 +42,10 @@ protected RequestFactory(OkHttpClient client, RequestValidator validator) {
         this.validator = validator;
     }
 
+    protected void setAutoClearCache(boolean autoClear) {
+        this.autoClearCache = autoClear;
+    }
+
     private OkHttpClient getClient() {
         File httpCacheDirectory = new File("./cacheDir", "http-cache");
         int cacheSize = 10 * 1024 * 1024; // 10 MiB
@@ -69,6 +74,8 @@ public void clearCache() {
     public CompletableFuture<JSONObject> sendAsync(Query query) {
         Request request = new Request.Builder().url(query.createRequest()).build();
 
+        if(autoClearCache) clearCache();
+
         return CompletableFuture.supplyAsync(() -> {
             try {
                 Response response = client.newCall(request).execute();
