diff --git a/aleksis/apps/cursus/frontend/components/Course.vue b/aleksis/apps/cursus/frontend/components/Course.vue
index 6e1b845ca905ef0eff253ed3f4a7b1db3c32cf3c..e79a29da79e6809aaaf06a48ac0863cf1740a5ab 100644
--- a/aleksis/apps/cursus/frontend/components/Course.vue
+++ b/aleksis/apps/cursus/frontend/components/Course.vue
@@ -17,7 +17,6 @@ import SubjectField from "./SubjectField.vue";
     :gql-create-mutation="gqlCreateMutation"
     :gql-patch-mutation="gqlPatchMutation"
     :gql-delete-mutation="gqlDeleteMutation"
-    :gql-delete-multiple-mutation="gqlDeleteMultipleMutation"
     :default-item="defaultItem"
     :get-create-data="transformCreateData"
     :get-patch-data="transformPatchData"
@@ -126,8 +125,7 @@ import SubjectField from "./SubjectField.vue";
 <script>
 import {
   courses,
-  createCourse,
-  deleteCourse,
+  createCourses,
   deleteCourses,
   updateCourses,
 } from "./course.graphql";
@@ -163,10 +161,9 @@ export default {
       ],
       i18nKey: "cursus.course",
       gqlQuery: courses,
-      gqlCreateMutation: createCourse,
+      gqlCreateMutation: createCourses,
       gqlPatchMutation: updateCourses,
-      gqlDeleteMutation: deleteCourse,
-      gqlDeleteMultipleMutation: deleteCourses,
+      gqlDeleteMutation: deleteCourses,
       defaultItem: {
         name: "",
         subject: null,
@@ -190,22 +187,20 @@ export default {
     };
   },
   methods: {
-    transformPatchData(items, headers) {
-      return items.map((item) => {
-        let dto = {};
-        headers.map((header) => {
-          if (header.value === "subject") {
-            dto["subject"] = item.subject?.id;
-          } else if (header.value === "groups") {
-            dto["groups"] = item.groups.map((group) => group.id);
-          } else if (header.value === "teachers") {
-            dto["teachers"] = item.teachers.map((teacher) => teacher.id);
-          } else {
-            dto[header.value] = item[header.value];
-          }
-        });
-        return dto;
+    transformPatchData(item) {
+      let dto = { id: item.id };
+      this.headers.map((header) => {
+        if (header.value === "subject") {
+          dto["subject"] = item.subject?.id;
+        } else if (header.value === "groups") {
+          dto["groups"] = item.groups?.map((group) => group.id);
+        } else if (header.value === "teachers") {
+          dto["teachers"] = item.teachers?.map((teacher) => teacher.id);
+        } else {
+          dto[header.value] = item[header.value];
+        }
       });
+      return dto;
     },
     transformCreateData(item) {
       return {
diff --git a/aleksis/apps/cursus/frontend/components/CreateCourse.vue b/aleksis/apps/cursus/frontend/components/CreateCourse.vue
index 877fc35fba420b3595d7311831bcdee7898f3402..d66cf9f980f85e469d6cc61f8780573526195cce 100644
--- a/aleksis/apps/cursus/frontend/components/CreateCourse.vue
+++ b/aleksis/apps/cursus/frontend/components/CreateCourse.vue
@@ -101,7 +101,7 @@ import CreateSubject from "./CreateSubject.vue";
 <script>
 import DialogObjectForm from "aleksis.core/components/generic/dialogs/DialogObjectForm.vue";
 
-import { subjects, createSubject } from "./subject.graphql";
+import { subjects, createSubjects } from "./subject.graphql";
 
 import { gqlGroups, gqlPersons } from "./helper.graphql";
 
@@ -119,7 +119,7 @@ export default {
     return {
       subject: {
         gqlQuery: subjects,
-        gqlCreateMutation: createSubject,
+        gqlCreateMutation: createSubjects,
         transformCreateData(item) {
           return { ...item, parent: item.parent?.id };
         },
diff --git a/aleksis/apps/cursus/frontend/components/SchoolStructure.vue b/aleksis/apps/cursus/frontend/components/SchoolStructure.vue
index e49a9e15ab5b3234132253b69a6dfa6059d20730..4ebb93ee5cc6aabba652e35b4d594d63eb5c7f7b 100644
--- a/aleksis/apps/cursus/frontend/components/SchoolStructure.vue
+++ b/aleksis/apps/cursus/frontend/components/SchoolStructure.vue
@@ -14,7 +14,7 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
       :default-item="createGradeDefaultItem"
       :is-create="true"
       create-item-i18n-key="cursus.school_structure.add_grade"
-      :gql-create-mutation="gqlCreateGrade"
+      :gql-create-mutation="gqlCreateGrades"
       :get-create-data="transformCreateGradeItem"
       @cancel="createGradeForm = false"
       @save="updateSchoolStructure"
@@ -26,7 +26,7 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
       :default-item="createClassDefaultItem"
       :is-create="true"
       create-item-i18n-key="cursus.school_structure.add_class"
-      :gql-create-mutation="gqlCreateClass"
+      :gql-create-mutation="gqlCreateClasses"
       :get-create-data="transformCreateClassItemForGrade"
       @cancel="createClassForm = false"
       @save="updateSchoolStructure"
@@ -148,8 +148,8 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
 <script>
 import {
   gqlSchoolGrades,
-  gqlCreateGrade,
-  gqlCreateClass,
+  gqlCreateGrades,
+  gqlCreateClasses,
 } from "./schoolStructure.graphql";
 
 export default {
diff --git a/aleksis/apps/cursus/frontend/components/Subject.vue b/aleksis/apps/cursus/frontend/components/Subject.vue
index 60671ce79b0dc94f33a909f376044206b013448c..4b5e20db28681b398afb8e125dd38634c54f447e 100644
--- a/aleksis/apps/cursus/frontend/components/Subject.vue
+++ b/aleksis/apps/cursus/frontend/components/Subject.vue
@@ -17,7 +17,6 @@ import SubjectChip from "./SubjectChip.vue";
     :gql-create-mutation="gqlCreateMutation"
     :gql-patch-mutation="gqlPatchMutation"
     :gql-delete-mutation="gqlDeleteMutation"
-    :gql-delete-multiple-mutation="gqlDeleteMultipleMutation"
     :default-item="defaultItem"
     :get-create-data="transformCreateData"
     :get-patch-data="transformPatchData"
@@ -143,8 +142,7 @@ import SubjectChip from "./SubjectChip.vue";
 <script>
 import {
   subjects,
-  createSubject,
-  deleteSubject,
+  createSubjects,
   deleteSubjects,
   updateSubjects,
 } from "./subject.graphql";
@@ -183,10 +181,9 @@ export default {
       ],
       i18nKey: "cursus.subject",
       gqlQuery: subjects,
-      gqlCreateMutation: createSubject,
+      gqlCreateMutation: createSubjects,
       gqlPatchMutation: updateSubjects,
-      gqlDeleteMutation: deleteSubject,
-      gqlDeleteMultipleMutation: deleteSubjects,
+      gqlDeleteMutation: deleteSubjects,
       defaultItem: {
         name: "",
         shortName: "",
@@ -209,20 +206,18 @@ export default {
     };
   },
   methods: {
-    transformPatchData(items, headers) {
-      return items.map((item) => {
-        let dto = {};
-        headers.map((header) => {
-          if (header.value === "parent") {
-            dto["parent"] = item.parent?.id;
-          } else if (header.value === "teachers") {
-            dto["teachers"] = item.teachers.map((teacher) => teacher.id);
-          } else {
-            dto[header.value] = item[header.value];
-          }
-        });
-        return dto;
+    transformPatchData(item) {
+      let dto = { id: item.id };
+      this.headers.map((header) => {
+        if (header.value === "parent") {
+          dto["parent"] = item.parent?.id;
+        } else if (header.value === "teachers") {
+          dto["teachers"] = item.teachers?.map((teacher) => teacher.id);
+        } else {
+          dto[header.value] = item[header.value];
+        }
       });
+      return dto;
     },
     transformCreateData(item) {
       return {
diff --git a/aleksis/apps/cursus/frontend/components/SubjectField.vue b/aleksis/apps/cursus/frontend/components/SubjectField.vue
index 6788d7e91c6fd83862cd5ce9991c8cdedaa47625..8f8f45f6354d99a48344425d3e1e127ffce1966b 100644
--- a/aleksis/apps/cursus/frontend/components/SubjectField.vue
+++ b/aleksis/apps/cursus/frontend/components/SubjectField.vue
@@ -31,8 +31,7 @@ import SubjectChip from "./SubjectChip.vue";
 <script>
 import {
   subjects,
-  createSubject,
-  deleteSubject,
+  createSubjects,
   deleteSubjects,
   updateSubjects,
 } from "./subject.graphql";
@@ -71,10 +70,9 @@ export default {
       ],
       i18nKey: "cursus.subject",
       gqlQuery: subjects,
-      gqlCreateMutation: createSubject,
+      gqlCreateMutation: createSubjects,
       gqlPatchMutation: updateSubjects,
-      gqlDeleteMutation: deleteSubject,
-      gqlDeleteMultipleMutation: deleteSubjects,
+      gqlDeleteMutation: deleteSubjects,
       defaultItem: {
         name: "",
         shortName: "",
diff --git a/aleksis/apps/cursus/frontend/components/course.graphql b/aleksis/apps/cursus/frontend/components/course.graphql
index a2e82899eaccfe53cb6f425714b9f74d9ed0a313..2a145e855646a2916487841415091be8aa923e05 100644
--- a/aleksis/apps/cursus/frontend/components/course.graphql
+++ b/aleksis/apps/cursus/frontend/components/course.graphql
@@ -22,32 +22,8 @@ query courses($orderBy: [String], $filters: JSONString) {
   }
 }
 
-mutation createCourse($input: CreateCourseInput!) {
-  createCourse(input: $input) {
-    item: course {
-      id
-      name
-      subject {
-        id
-        name
-      }
-      teachers {
-        id
-        fullName
-      }
-      groups {
-        id
-        name
-      }
-      lessonQuota
-      canEdit
-      canDelete
-    }
-  }
-}
-
-mutation batchCreateCourse($input: [BatchCreateCourseInput]!) {
-  batchCreateCourse(input: $input) {
+mutation createCourses($input: [BatchCreateCourseInput]!) {
+  createCourses(input: $input) {
     items: courses {
       id
       name
@@ -70,12 +46,6 @@ mutation batchCreateCourse($input: [BatchCreateCourseInput]!) {
   }
 }
 
-mutation deleteCourse($id: ID!) {
-  deleteCourse(id: $id) {
-    ok
-  }
-}
-
 mutation deleteCourses($ids: [ID]!) {
   deleteCourses(ids: $ids) {
     deletionCount
@@ -83,7 +53,7 @@ mutation deleteCourses($ids: [ID]!) {
 }
 
 mutation updateCourses($input: [BatchPatchCourseInput]!) {
-  batchMutation: updateCourses(input: $input) {
+  updateCourses(input: $input) {
     items: courses {
       id
       name
diff --git a/aleksis/apps/cursus/frontend/components/schoolStructure.graphql b/aleksis/apps/cursus/frontend/components/schoolStructure.graphql
index caf453a4a42114294211349d5226d7e72ad5c63c..269bee126f97789b705a31371b9782d6be1f60ed 100644
--- a/aleksis/apps/cursus/frontend/components/schoolStructure.graphql
+++ b/aleksis/apps/cursus/frontend/components/schoolStructure.graphql
@@ -15,9 +15,9 @@ query gqlSchoolGrades($schoolTerm: ID!) {
   }
 }
 
-mutation gqlCreateGrade($input: CreateGroupInput!) {
-  createGrade(input: $input) {
-    grade: group {
+mutation gqlCreateGrades($input: [BatchCreateGroupInput]!) {
+  createGrades(input: $input) {
+    grades: groups {
       id
       name
       shortName
@@ -28,9 +28,9 @@ mutation gqlCreateGrade($input: CreateGroupInput!) {
   }
 }
 
-mutation gqlCreateClass($input: CreateGroupInput!) {
-  createClass(input: $input) {
-    class: group {
+mutation gqlCreateClasses($input: [BatchCreateGroupInput]!) {
+  createClasses(input: $input) {
+    classes: groups {
       id
       name
       shortName
diff --git a/aleksis/apps/cursus/frontend/components/subject.graphql b/aleksis/apps/cursus/frontend/components/subject.graphql
index b635505cc2e71d2086b7cd380c14f329bb049807..2ce0fb85ee28b59ebd42bdc105420de91e85f433 100644
--- a/aleksis/apps/cursus/frontend/components/subject.graphql
+++ b/aleksis/apps/cursus/frontend/components/subject.graphql
@@ -20,9 +20,9 @@ query subjects($orderBy: [String], $filters: JSONString) {
   }
 }
 
-mutation createSubject($input: CreateSubjectInput!) {
-  createSubject(input: $input) {
-    item: subject {
+mutation createSubjects($input: [BatchCreateSubjectInput]!) {
+  createSubjects(input: $input) {
+    items: subjects {
       id
       name
       shortName
@@ -42,12 +42,6 @@ mutation createSubject($input: CreateSubjectInput!) {
   }
 }
 
-mutation deleteSubject($id: ID!) {
-  deleteSubject(id: $id) {
-    ok
-  }
-}
-
 mutation deleteSubjects($ids: [ID]!) {
   deleteSubjects(ids: $ids) {
     deletionCount
@@ -55,7 +49,7 @@ mutation deleteSubjects($ids: [ID]!) {
 }
 
 mutation updateSubjects($input: [BatchPatchSubjectInput]!) {
-  batchMutation: updateSubjects(input: $input) {
+  updateSubjects(input: $input) {
     items: subjects {
       id
       name
diff --git a/aleksis/apps/cursus/schema.py b/aleksis/apps/cursus/schema.py
index 477113cbacb8ad7f1ae9b9e191e200bc996cecdd..0e2a3d3269218fffa7d39f8694ab4236614d80e9 100644
--- a/aleksis/apps/cursus/schema.py
+++ b/aleksis/apps/cursus/schema.py
@@ -8,13 +8,11 @@ from graphene_django_cud.mutations import (
     DjangoBatchCreateMutation,
     DjangoBatchDeleteMutation,
     DjangoBatchPatchMutation,
-    DjangoCreateMutation,
 )
 from guardian.shortcuts import get_objects_for_user
 
 from aleksis.core.models import Group, GroupType, Person
 from aleksis.core.schema.base import (
-    DeleteMutation,
     DjangoFilterMixin,
     FilterOrderList,
     PermissionBatchDeleteMixin,
@@ -63,7 +61,7 @@ class SubjectType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType):
         return get_objects_for_user(info.context.user, "cursus.view_course", root.courses.all())
 
 
-class SubjectCreateMutation(DjangoCreateMutation):
+class SubjectBatchCreateMutation(DjangoBatchCreateMutation):
     class Meta:
         model = Subject
         permissions = ("cursus.create_subject_rule",)
@@ -78,11 +76,6 @@ class SubjectCreateMutation(DjangoCreateMutation):
         )
 
 
-class SubjectDeleteMutation(DeleteMutation):
-    klass = Subject
-    permission_required = "cursus.delete_subject_rule"
-
-
 class SubjectBatchDeleteMutation(PermissionBatchDeleteMixin, DjangoBatchDeleteMutation):
     class Meta:
         model = Subject
@@ -164,13 +157,6 @@ class CourseType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType):
         # return get_objects_for_user(info.context.user, "cursus.view_course", Course)
 
 
-class CourseCreateMutation(DjangoCreateMutation):
-    class Meta:
-        model = Course
-        permissions = ("cursus.create_course_rule",)
-        only_fields = ("name", "subject", "teachers", "groups", "lesson_quota")
-
-
 class CourseBatchCreateMutation(DjangoBatchCreateMutation):
     class Meta:
         model = Course
@@ -178,11 +164,6 @@ class CourseBatchCreateMutation(DjangoBatchCreateMutation):
         only_fields = ("name", "subject", "teachers", "groups", "lesson_quota")
 
 
-class CourseDeleteMutation(DeleteMutation):
-    klass = Course
-    permission_required = "cursus.delete_course_rule"
-
-
 class CourseBatchDeleteMutation(PermissionBatchDeleteMixin, DjangoBatchDeleteMutation):
     class Meta:
         model = Course
@@ -196,7 +177,7 @@ class CourseBatchPatchMutation(PermissionBatchPatchMixin, DjangoBatchPatchMutati
         only_fields = ("id", "name", "subject", "teachers", "groups", "lesson_quota")
 
 
-class CreateSchoolClassMutation(DjangoCreateMutation):
+class CreateSchoolClassMutation(DjangoBatchCreateMutation):
     class Meta:
         model = Group
         permissions = ("core.add_group",)
@@ -208,11 +189,12 @@ class CreateSchoolClassMutation(DjangoCreateMutation):
         group_type, __ = GroupType.objects.managed_by_app(app_label).get_or_create(
             name="School class", managed_by_app_label=app_label
         )
-        input["group_type"] = group_type.pk
+        for school_class in input:
+            school_class["group_type"] = group_type.pk
         return input
 
 
-class CreateSchoolGradeMutation(DjangoCreateMutation):
+class CreateSchoolGradeMutation(DjangoBatchCreateMutation):
     class Meta:
         model = Group
         permissions = ("core.add_group",)
@@ -224,7 +206,8 @@ class CreateSchoolGradeMutation(DjangoCreateMutation):
         group_type, __ = GroupType.objects.managed_by_app(app_label).get_or_create(
             name=SCHOOL_GRADE_GROUP_TYPE_NAME, managed_by_app_label=app_label
         )
-        input["group_type"] = group_type.pk
+        for school_grade in input:
+            school_grade["group_type"] = group_type.pk
         return input
 
 
@@ -293,16 +276,13 @@ class Query(graphene.ObjectType):
 
 
 class Mutation(graphene.ObjectType):
-    create_subject = SubjectCreateMutation.Field()
-    delete_subject = SubjectDeleteMutation.Field()
+    create_subjects = SubjectBatchCreateMutation.Field()
     delete_subjects = SubjectBatchDeleteMutation.Field()
     update_subjects = SubjectBatchPatchMutation.Field()
 
-    create_course = CourseCreateMutation.Field()
-    batch_create_course = CourseBatchCreateMutation.Field()
-    delete_course = CourseDeleteMutation.Field()
+    create_courses = CourseBatchCreateMutation.Field()
     delete_courses = CourseBatchDeleteMutation.Field()
     update_courses = CourseBatchPatchMutation.Field()
 
-    create_grade = CreateSchoolGradeMutation.Field()
-    create_class = CreateSchoolClassMutation.Field()
+    create_grades = CreateSchoolGradeMutation.Field()
+    create_classes = CreateSchoolClassMutation.Field()
diff --git a/pyproject.toml b/pyproject.toml
index 0a229883233684df0f867b218f33de2c27503df0..a4445aeee28a38496b5bbc298d4f7809169ebb11 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -35,7 +35,7 @@ priority = "supplemental"
 
 [tool.poetry.dependencies]
 python = "^3.10"
-aleksis-core = "^4.0.0.dev3"
+aleksis-core = "^4.0.0.dev4"
 
 [tool.poetry.plugins."aleksis.app"]
 cursus = "aleksis.apps.cursus.apps:DefaultConfig"