diff --git a/app/corpora/routes.py b/app/corpora/routes.py
index 8a3e5e66f950d079a6177cff80531d6a01aa02ff..148f5775aa40401ceb272d7d519bf22a43e3b51a 100644
--- a/app/corpora/routes.py
+++ b/app/corpora/routes.py
@@ -116,20 +116,6 @@ def analyse_corpus(corpus_id):
     )
 
 
-@bp.route('/<hashid:corpus_id>/generate-corpus-share-link', methods=['GET', 'POST'])
-@login_required
-@corpus_follower_permission_required('GENERATE_SHARE_LINK')
-def generate_corpus_share_link(corpus_id):
-    corpus_hashid = hashids.encode(corpus_id)
-    data = request.get_json('data')
-    role_name = data['role']
-    exp_data = data['expiration']
-    expiration = datetime.strptime(exp_data, '%b %d, %Y')
-    token = current_user.generate_follow_corpus_token(corpus_hashid, role_name, expiration)
-    link = url_for('corpora.follow_corpus', corpus_id=corpus_id, token=token, _external=True)
-    return link
-
-
 @bp.route('/<hashid:corpus_id>/follow/<token>')
 @login_required
 def follow_corpus(corpus_id, token):
@@ -210,6 +196,43 @@ def build_corpus(corpus_id):
     return response
 
 
+@bp.route('/<hashid:corpus_id>/generate-corpus-share-link', methods=['POST'])
+@login_required
+@corpus_follower_permission_required('GENERATE_SHARE_LINK')
+@content_negotiation(consumes='application/json', produces='application/json')
+def generate_corpus_share_link(corpus_id):
+    corpus_hashid = hashids.encode(corpus_id)
+    data = request.json
+    if not isinstance(data, dict):
+        abort(400)
+    expiration = data.get('expiration')
+    if not isinstance(expiration, str):
+        abort(400)
+    role_name = data.get('role')
+    if not isinstance(role_name, str):
+        abort(400)
+    expiration_date = datetime.strptime(expiration, '%b %d, %Y')
+    cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
+    if cfr is None:
+        abort(400)
+    token = current_user.generate_follow_corpus_token(corpus_hashid, role_name, expiration_date)
+    corpus_share_link = url_for(
+        'corpora.follow_corpus',
+        corpus_id=corpus_id,
+        token=token,
+        _external=True
+    )
+    response_data = {
+        'message': 'Corpus share link generated',
+        'category': 'corpus',
+        'corpusShareLink': corpus_share_link
+    }
+    response = jsonify(response_data)
+    response.status_code = 200
+    return response
+    
+
+
 @bp.route('/<hashid:corpus_id>/is_public', methods=['PUT'])
 @login_required
 @corpus_owner_or_admin_required
@@ -405,7 +428,9 @@ def add_permission(corpus_id, follower_id):
     role_name = request.json
     if not isinstance(role_name, str):
         abort(400)
-    cfr = CorpusFollowerRole.query.filter_by(name=role_name).first_or_404()
+    cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
+    if cfr is None:
+        abort(400)
     cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
     cfa.role = cfr
     db.session.commit()
diff --git a/app/static/js/Requests/Requests.js b/app/static/js/Requests/Requests.js
index 41f05a7fb422f5464b3919d4a9d32b9b9120c90a..ae3016f93ddb24a650bfd8e178d396456aa92976 100644
--- a/app/static/js/Requests/Requests.js
+++ b/app/static/js/Requests/Requests.js
@@ -11,6 +11,14 @@ Requests.JSONfetch = (input, init={}) => {
     fetch(input, Utils.mergeObjectsDeep(init, fixedInit))
       .then(
         (response) => {
+          if (response.ok) {
+            resolve(response.clone());
+          } else {
+            reject(response);
+          }
+          if (response.status === 204) {
+            return;
+          } 
           response.json()
             .then(
               (json) => {
@@ -22,11 +30,6 @@ Requests.JSONfetch = (input, init={}) => {
                 app.flash(`[${response.status}]: ${response.statusText}`, 'error');
               }
             );
-          if (response.ok) {
-            resolve(response);
-          } else {
-            reject(response);
-          }
         },
         (response) => {
           app.flash('Something went wrong', 'error');
diff --git a/app/static/js/Requests/corpora/corpora.js b/app/static/js/Requests/corpora/corpora.js
index 051fb07f4c5a0923113f1025bc95050f55789579..34593d952b5d8c274e5902ed8984c79cef010487 100644
--- a/app/static/js/Requests/corpora/corpora.js
+++ b/app/static/js/Requests/corpora/corpora.js
@@ -4,9 +4,9 @@
 *****************************************************************************/
 Requests.corpora = {};
 
-Requests.corpora.ent = {};
+Requests.corpora.entity = {};
 
-Requests.corpora.ent.delete = (corpusId) => {
+Requests.corpora.entity.delete = (corpusId) => {
   let input = `/corpora/${corpusId}`;
   let init = {
     method: 'DELETE'
@@ -14,7 +14,7 @@ Requests.corpora.ent.delete = (corpusId) => {
   return Requests.JSONfetch(input, init);
 };
 
-Requests.corpora.ent.build = (corpusId) => {
+Requests.corpora.entity.build = (corpusId) => {
   let input = `/corpora/${corpusId}/build`;
   let init = {
     method: 'POST',
@@ -22,57 +22,25 @@ Requests.corpora.ent.build = (corpusId) => {
   return Requests.JSONfetch(input, init);
 };
 
-Requests.corpora.ent.isPublic = {};
-
-Requests.corpora.ent.isPublic.update = (corpusId, value) => {
-  let input = `/corpora/${corpusId}/is_public`;
-  let init = {
-    method: 'PUT',
-    body: JSON.stringify(value)
-  };
-  return Requests.JSONfetch(input, init);
-};
-
-Requests.corpora.ent.files = {};
-
-Requests.corpora.ent.files.ent = {};
-
-Requests.corpora.ent.files.ent.delete = (corpusId, corpusFileId) => {
-  let input = `/corpora/${corpusId}/files/${corpusFileId}`;
-  let init = {
-    method: 'DELETE',
-  };
-  return Requests.JSONfetch(input, init);
-};
-
-Requests.corpora.ent.followers = {};
-
-Requests.corpora.ent.followers.add = (corpusId, usernames) => {
-  let input = `/corpora/${corpusId}/followers`;
+Requests.corpora.entity.generateShareLink = (corpusId, role, expiration) => {
+  let input = `/corpora/${corpusId}/generate-corpus-share-link`;
   let init = {
     method: 'POST',
-    body: JSON.stringify(usernames)
+    body: JSON.stringify({role: role, expiration: expiration})
   };
   return Requests.JSONfetch(input, init);
 };
 
-Requests.corpora.ent.followers.ent = {};
+Requests.corpora.entity.isPublic = {};
 
-Requests.corpora.ent.followers.ent.delete = (corpusId, followerId) => {
-  let input = `/corpora/${corpusId}/followers/${followerId}`;
-  let init = {
-    method: 'DELETE',
-  };
-  return Requests.JSONfetch(input, init);
-};
-
-Requests.corpora.ent.followers.ent.role = {};
-
-Requests.corpora.ent.followers.ent.role.update = (corpusId, followerId, value) => {
-  let input = `/corpora/${corpusId}/followers/${followerId}/role`;
+Requests.corpora.entity.isPublic.update = (corpusId, value) => {
+  let input = `/corpora/${corpusId}/is_public`;
   let init = {
     method: 'PUT',
     body: JSON.stringify(value)
   };
   return Requests.JSONfetch(input, init);
 };
+
+
+
diff --git a/app/static/js/Requests/corpora/files.js b/app/static/js/Requests/corpora/files.js
new file mode 100644
index 0000000000000000000000000000000000000000..9ff9ba8730fa127ecc6f73cc0cff424302001990
--- /dev/null
+++ b/app/static/js/Requests/corpora/files.js
@@ -0,0 +1,15 @@
+/*****************************************************************************
+* Corpora                                                                    *
+* Fetch requests for /corpora/<entity>/files routes                          *
+*****************************************************************************/
+Requests.corpora.entity.files = {};
+
+Requests.corpora.entity.files.ent = {};
+
+Requests.corpora.entity.files.ent.delete = (corpusId, corpusFileId) => {
+  let input = `/corpora/${corpusId}/files/${corpusFileId}`;
+  let init = {
+    method: 'DELETE',
+  };
+  return Requests.JSONfetch(input, init);
+};
diff --git a/app/static/js/Requests/corpora/followers.js b/app/static/js/Requests/corpora/followers.js
new file mode 100644
index 0000000000000000000000000000000000000000..f7f7877f47aec13469a02e915cabbb2bf970a2e4
--- /dev/null
+++ b/app/static/js/Requests/corpora/followers.js
@@ -0,0 +1,35 @@
+/*****************************************************************************
+* Corpora                                                                    *
+* Fetch requests for /corpora/<entity>/followers routes                      *
+*****************************************************************************/
+Requests.corpora.entity.followers = {};
+
+Requests.corpora.entity.followers.add = (corpusId, usernames) => {
+  let input = `/corpora/${corpusId}/followers`;
+  let init = {
+    method: 'POST',
+    body: JSON.stringify(usernames)
+  };
+  return Requests.JSONfetch(input, init);
+};
+
+Requests.corpora.entity.followers.entity = {};
+
+Requests.corpora.entity.followers.entity.delete = (corpusId, followerId) => {
+  let input = `/corpora/${corpusId}/followers/${followerId}`;
+  let init = {
+    method: 'DELETE',
+  };
+  return Requests.JSONfetch(input, init);
+};
+
+Requests.corpora.entity.followers.entity.role = {};
+
+Requests.corpora.entity.followers.entity.role.update = (corpusId, followerId, value) => {
+  let input = `/corpora/${corpusId}/followers/${followerId}/role`;
+  let init = {
+    method: 'PUT',
+    body: JSON.stringify(value)
+  };
+  return Requests.JSONfetch(input, init);
+};
diff --git a/app/static/js/ResourceDisplays/CorpusDisplay.js b/app/static/js/ResourceDisplays/CorpusDisplay.js
index 07f0a9be59f2a71f21f5e713e236c4d32dea4ec7..ef9dc8b84333f45a83a7ea44eb241b724d6c1133 100644
--- a/app/static/js/ResourceDisplays/CorpusDisplay.js
+++ b/app/static/js/ResourceDisplays/CorpusDisplay.js
@@ -5,7 +5,7 @@ class CorpusDisplay extends ResourceDisplay {
     this.displayElement
       .querySelector('.action-button[data-action="build-request"]')
       .addEventListener('click', (event) => {
-        Requests.corpora.corpus.build(this.corpusId);
+        Requests.corpora.entity.build(this.corpusId);
       });
   }
 
diff --git a/app/static/js/ResourceLists/CorpusFollowerList.js b/app/static/js/ResourceLists/CorpusFollowerList.js
index b0b621d2c361c652bb9b888d3f0e4c082662a7fa..826293546d323803dc00c035229c3143d30deaaf 100644
--- a/app/static/js/ResourceLists/CorpusFollowerList.js
+++ b/app/static/js/ResourceLists/CorpusFollowerList.js
@@ -122,7 +122,7 @@ class CorpusFollowerList extends ResourceList {
       case 'update-role': {
         let followerId = listItemElement.dataset.followerId;
         let roleName = event.target.value;
-        Utils.updateCorpusFollowerRole(this.corpusId, followerId, roleName);
+        Requests.corpora.entity.followers.entity.role.update(this.corpusId, followerId, roleName);
         break;
       }
       default: {
@@ -141,7 +141,7 @@ class CorpusFollowerList extends ResourceList {
     switch (listAction) {
       case 'unfollow-request': {
         let followerId = listItemElement.dataset.followerId;
-        Utils.unfollowCorpusRequest(this.corpusId, followerId);
+        Requests.corpora.entity.followers.entity.delete(this.corpusId, followerId);
         break;
       }
       case 'view': {
diff --git a/app/static/js/ResourceLists/CorpusList.js b/app/static/js/ResourceLists/CorpusList.js
index bf62ebed1b69e1b67f3cc327609d2e6cee30b736..7d43167380c04ee67d08b4d6f7a9727793243b69 100644
--- a/app/static/js/ResourceLists/CorpusList.js
+++ b/app/static/js/ResourceLists/CorpusList.js
@@ -95,7 +95,7 @@ class CorpusList extends ResourceList {
     let listAction = listActionElement === null ? 'view' : listActionElement.dataset.listAction;
     switch (listAction) {
       case 'delete-request': {
-        Utils.deleteCorpusRequest(this.userId, itemId);
+        Requests.corpora.entity.delete(this.userId, itemId);
         break;
       }
       case 'view': {
diff --git a/app/static/js/Utils.js b/app/static/js/Utils.js
index 88dadea1dff44847eff5275bdd28629311fc9891..b77e4dd0a5624f35fd51b5d3c7ceb8a361fe7472 100644
--- a/app/static/js/Utils.js
+++ b/app/static/js/Utils.js
@@ -69,151 +69,6 @@ class Utils {
     return Utils.mergeObjectsDeep(mergedObject, ...objects.slice(2));
   }
 
-  static updateCorpusIsPublicRequest(corpusId, isPublic) {
-    return new Promise((resolve, reject) => {
-      let fetchRessource = `/corpora/${corpusId}/is_public`;
-      let fetchOptions = {
-        method: 'POST',
-        headers: {
-          'Accept': 'application/json',
-          'Content-Type': 'application/json'
-        },
-        body: JSON.stringify(isPublic)
-      };
-      fetch(fetchRessource, fetchOptions)
-        .then(
-          (response) => {
-            if (response.ok) {
-              app.flash(`Corpus is now ${isPublic ? 'public' : 'private'}`, 'corpus');
-              resolve(response);
-            } else {
-              app.flash(`${response.statusText}`, 'error');
-              reject(response);
-            }
-          },
-          (response) => {
-            app.flash('Something went wrong', 'error');
-            reject(response);
-          }
-        );
-    });
-  }
-
-  static updateCorpusFollowerRole(corpusId, followerId, roleName) {
-    return new Promise((resolve, reject) => {
-      let fetchRessource = `/corpora/${corpusId}/followers/${followerId}/role`;
-      let fetchOptions = {
-        method: 'POST',
-        headers: {
-          'Accept': 'application/json',
-          'Content-Type': 'application/json'
-        },
-        body: JSON.stringify({role: roleName})
-      };
-      fetch(fetchRessource, fetchOptions)
-        .then(
-          (response) => {
-            if (response.ok) {
-              app.flash('Role updated', 'corpus');
-              resolve(response);
-            } else {
-              app.flash(`${response.statusText}`, 'error');
-              reject(response);
-            }
-          },
-          (response) => {
-            app.flash('Something went wrong', 'error');
-            reject(response);
-          }
-        );
-    });
-  }
-
-  static addCorpusFollowersRequest(corpusId, usernames) {
-    return new Promise((resolve, reject) => {
-      let fetchRessource = `/corpora/${corpusId}/followers/add`;
-      let fetchOptions = {
-        method: 'POST',
-        headers: {
-          'Accept': 'application/json',
-          'Content-Type': 'application/json'
-        },
-        body: JSON.stringify(usernames)
-      };
-      fetch(fetchRessource, fetchOptions)
-        .then(
-          (response) => {
-            if (response.ok) {
-              app.flash(`${usernames.length > 1 ? 'Users are' : 'User is'} following now`, 'corpus');
-              resolve(response);
-            } else {
-              app.flash(`${response.statusText}`, 'error');
-              reject(response);
-            }
-          },
-          (response) => {
-            app.flash('Something went wrong', 'error');
-            reject(response);
-          }
-        );
-    });
-  }
-
-  static buildCorpusRequest(userId, corpusId) {
-    return new Promise((resolve, reject) => {
-      let corpus;
-      try {
-        corpus = app.data.users[userId].corpora[corpusId];
-      } catch (error) {
-        corpus = {};
-      }
-
-      fetch(`/corpora/${corpusId}/build`, {method: 'POST', headers: {Accept: 'application/json'}})
-        .then(
-          (response) => {
-            if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
-            if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
-            if (response.status === 409) {app.flash('Conflict', 'error'); reject(response);}
-            app.flash(`Corpus "${corpus?.title}" marked for building`, 'corpus');
-            resolve(response);
-          },
-          (response) => {
-            app.flash('Something went wrong', 'error');
-            reject(response);
-          }
-        );
-    });
-  }
-
-  static unfollowCorpusRequest(corpusId, followerId) {
-    return new Promise((resolve, reject) => {
-      let fetchRessource = `/corpora/${corpusId}/followers/${followerId}/unfollow`;
-      let fetchOptions = {
-        method: 'POST',
-        headers: {
-          'Accept': 'application/json',
-          'Content-Type': 'application/json'
-        }
-      };
-      fetch(fetchRessource, fetchOptions)
-        .then(
-          (response) => {
-            if (response.ok) {
-              app.flash(`User unfollowed from Corpus`, 'corpus');
-              resolve(response);
-            } else {
-              app.flash(`${response.statusText}`, 'error');
-              reject(response);
-            }
-          },
-          (response) => {
-            app.flash('Something went wrong', 'error');
-            reject(response);
-          }
-        );
-    });
-  }
-
   static deleteCorpusRequest(userId, corpusId) {
     return new Promise((resolve, reject) => {
       let corpus;
@@ -326,116 +181,6 @@ class Utils {
     });
   }
 
-  static deleteSpaCyNLPPipelineModelRequest(userId, spaCyNLPPipelineModelId) {
-    return new Promise((resolve, reject) => {
-      let spaCyNLPPipelineModel;
-      try {
-        spaCyNLPPipelineModel = app.data.users[userId].spacy_nlp_pipeline_models[spaCyNLPPipelineModelId];
-      } catch (error) {
-        spaCyNLPPipelineModel = {};
-      }
-
-      let modalElement = Utils.HTMLToElement(
-        `
-          <div class="modal">
-            <div class="modal-content">
-              <h4>Confirm SpaCy NLP Pipeline Model deletion</h4>
-              <p>Do you really want to delete the SpaCy NLP Pipeline Model <b>${spaCyNLPPipelineModel?.title}</b>? All files will be permanently deleted!</p>
-            </div>
-            <div class="modal-footer">
-              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
-              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
-            </div>
-          </div>
-        `
-      );
-      document.querySelector('#modals').appendChild(modalElement);
-      let modal = M.Modal.init(
-        modalElement,
-        {
-          dismissible: false,
-          onCloseEnd: () => {
-            modal.destroy();
-            modalElement.remove();
-          }
-        }
-      );
-      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
-      confirmElement.addEventListener('click', (event) => {
-        let spaCyNLPPipelineModelTitle = spaCyNLPPipelineModel?.title;
-        fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModelId}`, {method: 'DELETE'})
-          .then(
-            (response) => {
-              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
-              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
-              app.flash(`SpaCy NLP Pipeline Model "${spaCyNLPPipelineModelTitle}" marked for deletion`);
-              resolve(response);
-            },
-            (response) => {
-              app.flash('Something went wrong', 'error');
-              reject(response);
-            }
-          );
-      });
-      modal.open();
-    });
-  }
-
-  static deleteTesseractOCRPipelineModelRequest(userId, tesseractOCRPipelineModelId) {
-    return new Promise((resolve, reject) => {
-      let tesseractOCRPipelineModel;
-      try {
-        tesseractOCRPipelineModel = app.data.users[userId].tesseract_ocr_pipeline_models[tesseractOCRPipelineModelId];
-      } catch (error) {
-        tesseractOCRPipelineModel = {};
-      }
-
-      let modalElement = Utils.HTMLToElement(
-        `
-          <div class="modal">
-            <div class="modal-content">
-              <h4>Confirm Tesseract OCR Pipeline Model deletion</h4>
-              <p>Do you really want to delete the Tesseract OCR Pipeline Model <b>${tesseractOCRPipelineModel?.title}</b>? All files will be permanently deleted!</p>
-            </div>
-            <div class="modal-footer">
-              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
-              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
-            </div>
-          </div>
-        `
-      );
-      document.querySelector('#modals').appendChild(modalElement);
-      let modal = M.Modal.init(
-        modalElement,
-        {
-          dismissible: false,
-          onCloseEnd: () => {
-            modal.destroy();
-            modalElement.remove();
-          }
-        }
-      );
-      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
-      confirmElement.addEventListener('click', (event) => {
-        let tesseractOCRPipelineModelTitle = tesseractOCRPipelineModel?.title;
-        fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}`, {method: 'DELETE'})
-          .then(
-            (response) => {
-              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
-              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
-              app.flash(`Tesseract OCR Pipeline Model "${tesseractOCRPipelineModelTitle}" marked for deletion`);
-              resolve(response);
-            },
-            (response) => {
-              app.flash('Something went wrong', 'error');
-              reject(response);
-            }
-          );
-      });
-      modal.open();
-    });
-  }
-
   static deleteProfileAvatarRequest(userId) {
     return new Promise((resolve, reject) => {
       let modalElement = Utils.HTMLToElement(
@@ -698,94 +443,4 @@ class Utils {
       modal.open();
     });
   }
-
-  static updateTesseractOCRPipelineModelIsPublicRequest(tesseractOCRPipelineModelId, newIsPublicValue) {
-    return new Promise((resolve, reject) => {
-      let fetchRessource = `/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}/is_public`;
-      let fetchOptions = {
-        method: 'PUT',
-        headers: {
-          'Accept': 'application/json',
-          'Content-Type': 'application/json'
-        },
-        body: JSON.stringify(newIsPublicValue)
-      };
-      fetch(fetchRessource, fetchOptions)
-        .then(
-          (response) => {
-            if (response.ok) {
-              response.json().then((data) => {app.flash(data);});
-              resolve(response);
-            } else {
-              app.flash(`${response.statusText}`, 'error');
-              reject(response);
-            }
-          },
-          (response) => {
-            app.flash('Something went wrong', 'error');
-            reject(response);
-          }
-        );
-    });
-  }
-
-  static updateSpaCyNLPPipelineModelIsPublicRequest(SpaCyNLPPipelineModelId, newIsPublicValue) {
-    return new Promise((resolve, reject) => {
-      let fetchRessource = `/contributions/spacy-nlp-pipeline-models/${SpaCyNLPPipelineModelId}/is_public`;
-      let fetchOptions = {
-        method: 'PUT',
-        headers: {
-          'Accept': 'application/json',
-          'Content-Type': 'application/json'
-        },
-        body: JSON.stringify(newIsPublicValue)
-      };
-      fetch(fetchRessource, fetchOptions)
-        .then(
-          (response) => {
-            if (response.ok) {
-              response.json().then((data) => {app.flash(data);});
-              resolve(response);
-            } else {
-              app.flash(`${response.statusText}`, 'error');
-              reject(response);
-            }
-          },
-          (response) => {
-            app.flash('Something went wrong', 'error');
-            reject(response);
-          }
-        );
-    });
-  }
-
-  static generateCorpusShareLinkRequest(corpusId, role, expiration) {
-    return new Promise((resolve, reject) => {
-      const data = {role: role, expiration: expiration};
-      fetch(`/corpora/${corpusId}/generate-corpus-share-link`, {method: 'POST', headers: {Accept: 'text/plain'}, body: JSON.stringify(data)})
-        .then(
-          (response) => {
-            if (!response.ok) {
-              app.flash(`Something went wrong: ${response.status} ${response.statusText}`, 'error');
-              reject(response);
-              return;
-            }
-            return response.text();
-          },
-          (response) => {
-            // Something went wrong during the HTTP request
-            app.flash('Something went wrong', 'error');
-            reject(response);
-          }
-        )
-        .then(
-          (corpusShareLink) => {resolve(corpusShareLink);},
-          (error) => {
-            // Something went wrong during ReadableStream processing
-            app.flash('Something went wrong', 'error');
-            reject(error);
-          }
-        );
-    });
-  }
 }
diff --git a/app/templates/_scripts.html.j2 b/app/templates/_scripts.html.j2
index 6fef8d1a0274f0bdbce79af8b09396536387efca..5bd2d83cb5ac70797d8f258de36da8fbc4cf7ab2 100644
--- a/app/templates/_scripts.html.j2
+++ b/app/templates/_scripts.html.j2
@@ -61,7 +61,9 @@
   'js/Requests/contributions/contributions.js',
   'js/Requests/contributions/spacy_nlp_pipeline_models.js',
   'js/Requests/contributions/tesseract_ocr_pipeline_models.js',
-  'js/Requests/Corpora.js'
+  'js/Requests/corpora/corpora.js',
+  'js/Requests/corpora/files.js',
+  'js/Requests/corpora/followers.js'
 %}
 <script src="{{ ASSET_URL }}"></script>
 {%- endassets %}
diff --git a/app/templates/corpora/corpus.html.j2 b/app/templates/corpora/corpus.html.j2
index 3174713f7abf61d6b79c4443c414684d1e4dc70f..d8577907d3ed93e84651236d7131c0600d082c53 100644
--- a/app/templates/corpora/corpus.html.j2
+++ b/app/templates/corpora/corpus.html.j2
@@ -226,7 +226,7 @@
   let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
   publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
     let newIsPublic = publishingModalIsPublicSwitchElement.checked;
-    Requests.corpora.corpus.isPublic.update(corpusId, newIsPublic)
+    Requests.corpora.entity.isPublic.update(corpusId, newIsPublic)
       .catch((response) => {
         publishingModalIsPublicSwitchElement.checked = !newIsPublic;
       });
@@ -236,7 +236,7 @@
   // #region delete_modal_js
   let deleteModalDeleteButtonElement = document.querySelector('#delete-modal-delete-button');
   deleteModalDeleteButtonElement.addEventListener('click', (event) => {
-    Requests.corpora.corpus.delete(corpusId)
+    Requests.corpora.entity.delete(corpusId)
       .then((response) => {window.location.href = '/dashboard';});
   });
   // #endregion delete_modal_js
@@ -280,7 +280,7 @@
 
   inviteUserModalInviteButtonElement.addEventListener('click', (event) => {
     let usernames = inviteUserModalSearch.chipsData.map((chipData) => chipData.tag);
-    Utils.addCorpusFollowersRequest(corpusId, usernames);
+    Requests.corpora.entity.followers.add(corpusId, usernames);
   });
   // #endregion invite_user_modal_js
 
@@ -323,10 +323,13 @@
   )
 
   shareLinkModalCreateButtonElement.addEventListener('click', (event) => {
-    Utils.generateCorpusShareLinkRequest(corpusId, shareLinkModalCorpusFollowerRoleSelectElement.value, shareLinkModalExpirationDateDatepickerElement.value)
-      .then((shareLink) => {
-        shareLinkModalOutputContainerElement.classList.remove('hide');
-        shareLinkModalOutputFieldElement.value = shareLink;
+    Requests.corpora.entity.generateShareLink(corpusId, shareLinkModalCorpusFollowerRoleSelectElement.value, shareLinkModalExpirationDateDatepickerElement.value)
+      .then((response) => {
+        response.json()
+          .then((json) => {
+            shareLinkModalOutputContainerElement.classList.remove('hide');
+            shareLinkModalOutputFieldElement.value = json.corpusShareLink;
+          });
       });
   });