diff --git a/src/util/API.js b/src/util/API.js
index f199e8d12b4fb8121fbf9780f19df42df0fd2efe..d156d481b691768a0403d48630ed0e1d845b80ba 100644
--- a/src/util/API.js
+++ b/src/util/API.js
@@ -5,128 +5,152 @@ import router from "@/router/index";
 
 export const API = {
 
-    /**
-     * API method to send a login request.
-     * If login succeeds, the logged in User and their token
-     * is saved to the Pinia AuthStore
-     *
-     * @param email email address of the user to log in as
-     * @param password password to log in with
-     * @returns a Result with whether the login attempt succeeded
-     */
-    login: async (request) => {
-        const authStore = useAuthStore();
-        let token;
-        authStore.logout(); //in case someone for some reason is logged in
-
-        return axios.post(
-            `${import.meta.env.VITE_BACKEND_URL}/login`,
-            request,
-          )
-            .then(async (response) => {
-              token = response.data;
-              const id = (jwt_decode(token)).id;
-
-              return API.getAccount(id, token)
-                .then((user) => {
-                  authStore.setAccount(user);
-                  authStore.setToken(token);
-                  API.getProfiles()
-                    .then(response => {authStore.setProfiles(response)})
-                    .catch(() => {throw new Error()})
-                  return;
-                })
-                .catch(() => {
-                  throw new Error();
-                });
-            })
-            .catch(() => {
-              throw new Error();
-            });
-        },
+  /**
+   * API method to send a login request.
+   * If login succeeds, the logged in User and their token
+   * is saved to the Pinia AuthStore
+   *
+   * @param email email address of the user to log in as
+   * @param password password to log in with
+   * @returns a Result with whether the login attempt succeeded
+   */
+  login: async (request) => {
+    const authStore = useAuthStore();
+    let token;
+    authStore.logout(); //in case someone for some reason is logged in
 
+    return axios.post(
+      `${import.meta.env.VITE_BACKEND_URL}/login`,
+      request,
+    )
+      .then(async (response) => {
+        token = response.data;
+        const id = (jwt_decode(token)).id;
 
-    /**
-     * API method to get a account by their ID
-     * @param id ID number of the account to retrieve
-     * @returns A promise that resolves to a User if the API call succeeds,
-     * or is rejected if the API call fails
-     */
-    getAccount: async (id, token) => {
-        return axios.get(`${import.meta.env.VITE_BACKEND_URL}/account/${id}`, {
-            headers: { Authorization: `Bearer ${token}` },
-          })
-          .then((response) => {
-            return response.data;
+        return API.getAccount(id, token)
+          .then((user) => {
+            authStore.setAccount(user);
+            authStore.setToken(token);
+            API.getProfiles()
+              .then(response => { authStore.setProfiles(response) })
+              .catch(() => { throw new Error() })
+            return;
           })
           .catch(() => {
-            throw new Error("Account not found or not accessible");
+            throw new Error();
           });
-      },
+      })
+      .catch(() => {
+        throw new Error();
+      });
+  },
 
-    // Sends the user into the home page logged in as the profile they clicked on
-    selectProfile: async (id) => {
-        const authStore = useAuthStore()
-        return axios.get(`${import.meta.env.VITE_BACKEND_URL}/profile/${id}`, {
-            headers: { Authorization: `Bearer ${authStore.token}` },
-          })
-          .then((response) => {
-            authStore.setProfile(response.data)
-            router.push("/")
 
-          })
-          .catch(() => {
-            throw new Error("Profile not found or not accessible")
-          })
+  /**
+   * API method to get a account by their ID
+   * @param id ID number of the account to retrieve
+   * @returns A promise that resolves to a User if the API call succeeds,
+   * or is rejected if the API call fails
+   */
+  getAccount: async (id, token) => {
+    return axios.get(`${import.meta.env.VITE_BACKEND_URL}/account/${id}`, {
+      headers: { Authorization: `Bearer ${token}` },
+    })
+      .then((response) => {
+        return response.data;
+      })
+      .catch(() => {
+        throw new Error("Account not found or not accessible");
+      });
+  },
 
+  // Sends the user into the home page logged in as the profile they clicked on
+  selectProfile: async (id) => {
+    const authStore = useAuthStore()
+    return axios.get(`${import.meta.env.VITE_BACKEND_URL}/profile/${id}`, {
+      headers: { Authorization: `Bearer ${authStore.token}` },
+    })
+      .then((response) => {
+        authStore.setProfile(response.data)
+        router.push("/")
 
-    },
+      })
+      .catch(() => {
+        throw new Error("Profile not found or not accessible")
+      })
+  },
 
-    /**
-     * Sends a request to create a new profile on the currently logged in account
-     *
-     * @typedef {{name: string, profileImageUrl: string, isRestricted: boolean}} ProfileType
-     * @param {ProfileType} profile
-     * @returns
-     */
-    addProfile: async (profile) => {
-      const authStore = useAuthStore();
-      if (!authStore.isLoggedIn) {
-          throw new Error();
-      }
+  /**
+   * Upload profile image
+   * 
+   * @param {Blob} image - the image file contents to upload. Must be a JPEG no bigger than 512kB
+   * @param {Number} profileId - the ID of the profile to upload this image to
+   * @returns {Promise<String>} A Promise that resolves to the URL of the uploaded image
+   */
+  uploadProfileImage: async (image, profileId) => {
+    const authStore = useAuthStore();
+
+    let fd = new FormData();
+    fd.append("file", image);
+    fd.append("profileId", profileId);
 
-      return axios.post(import.meta.env.VITE_BACKEND_URL + '/profile', {
-        headers: { Authorization: "Bearer " + authStore.token },
-        body: profile
+    return axios.post(`${import.meta.env.VITE_BACKEND_URL}/img`, fd, {
+      headers: {
+        Authorization: `Bearer ${authStore.token}`,
+      }
+    })
+      .then((response) => {
+        return response.data;
+      })
+      .catch(() => {
+        throw new Error();
       })
+  },
+
+  /**
+   * Sends a request to create a new profile on the currently logged in account
+   * 
+   * @typedef {{name: string, id?: number, accountId?: number, profileImageUrl: string, isRestricted: boolean}} ProfileType
+   * @param {ProfileType} profile  - the partial data of profile to create
+   * @returns {Promise<ProfileType>} the full profile after saving, with id and account ID set
+   */
+  addProfile: async (profile) => {
+    const authStore = useAuthStore();
+    if (!authStore.isLoggedIn) {
+      throw new Error();
+    }
+
+    return axios.post(import.meta.env.VITE_BACKEND_URL + '/profile', profile,  {
+      headers: { Authorization: "Bearer " + authStore.token },
+    })
       .then((response) => {
         return response.data;
       }).catch(() => {
         throw new Error();
       })
-    },
+  },
 
-    // Returns all profiles to the logged in user
-    getProfiles: async () => {
-        const authStore = useAuthStore();
-        if (!authStore.isLoggedIn) {
-            throw new Error();
-        }
-
-        return axios.get(import.meta.env.VITE_BACKEND_URL + '/profile', {
-            headers: { Authorization: "Bearer " + authStore.token },
-          },
-        )
-          .then(response => {
-            return response.data
-          }).catch(() => {
-            throw new Error();
-          });
+  // Returns all profiles to the logged in user
+  getProfiles: async () => {
+    const authStore = useAuthStore();
+    if (!authStore.isLoggedIn) {
+      throw new Error();
+    }
+
+    return axios.get(import.meta.env.VITE_BACKEND_URL + '/profile', {
+      headers: { Authorization: "Bearer " + authStore.token },
     },
+    )
+      .then(response => {
+        return response.data
+      }).catch(() => {
+        throw new Error();
+      });
+  },
 
-    // Registers a new account and logs into it
-    addAccount: async (request) => {
-        const authStore = useAuthStore();
+  // Registers a new account and logs into it
+  addAccount: async (request) => {
+    const authStore = useAuthStore();
 
         axios.post(import.meta.env.VITE_BACKEND_URL + '/account', request)
         .then(() => {