diff --git a/arkindex/documents/api/ml.py b/arkindex/documents/api/ml.py
index a951a0bb6b25b030377e0306e23e4d2a031ef5d0..224b4c35250a3541294da461d618412cd9c270bd 100644
--- a/arkindex/documents/api/ml.py
+++ b/arkindex/documents/api/ml.py
@@ -54,6 +54,8 @@ class TranscriptionCreate(ACLMixin, CreateAPIView):
     def get_object(self):
         if not hasattr(self, 'element'):
             self.element = super().get_object()
+            if not self.has_access(self.element.corpus, Role.Contributor.value):
+                raise PermissionDenied(detail="A write access to the element's corpus is required.")
         return self.element
 
     def get_queryset(self):
@@ -65,8 +67,11 @@ class TranscriptionCreate(ACLMixin, CreateAPIView):
         # We retrieve the readable objects then check permissions
         # instead of retrieving writable objects directly so as not to
         # get 404_NOT_FOUND errors on elements the user has access to.
-        return Element.objects.using('default').filter(
-            corpus__in=Corpus.objects.readable(self.request.user)
+        return (
+            Element.objects
+            .using('default')
+            .filter(corpus__in=Corpus.objects.readable(self.request.user))
+            .select_related('corpus')
         )
 
     def get_serializer_context(self):
@@ -75,23 +80,10 @@ class TranscriptionCreate(ACLMixin, CreateAPIView):
             context['element'] = self.get_object()
         return context
 
-    def check_object_permissions(self, request, context):
-        super().check_object_permissions(request, context)
-        role = Role.Contributor
-        detail = "A write access to the element's corpus is required."
-        if not self.has_access(context.corpus, role.value):
-            raise PermissionDenied(detail=detail)
-
-    def perform_create(self, serializer):
-        return Transcription.objects.create(
-            element=self.element,
-            **serializer.validated_data
-        )
-
     def create(self, request, *args, **kwargs):
         serializer = self.get_serializer(data=request.data)
         serializer.is_valid(raise_exception=True)
-        obj = self.perform_create(serializer)
+        obj = serializer.save()
         headers = self.get_success_headers(serializer.data)
         return Response(
             # Use a single transcription serializer for the response
diff --git a/arkindex/documents/serializers/ml.py b/arkindex/documents/serializers/ml.py
index fe42b74ad6791ce40acabd775f56b55244fdeb57..894aa2ac3c40bcb52b645873228fb7b48af19e70 100644
--- a/arkindex/documents/serializers/ml.py
+++ b/arkindex/documents/serializers/ml.py
@@ -362,6 +362,12 @@ class TranscriptionCreateSerializer(serializers.ModelSerializer):
 
         return data
 
+    def create(self, validated_data):
+        return Transcription.objects.create(
+            element=self.context['element'],
+            **validated_data,
+        )
+
 
 class SimpleTranscriptionSerializer(serializers.Serializer):
     """
diff --git a/arkindex/documents/tests/test_create_transcriptions.py b/arkindex/documents/tests/test_create_transcriptions.py
index 6020b1edff1e2845c5a118068963e45709bc4584..7d7769aca7ddbb895d060c2e1e563a7920344648 100644
--- a/arkindex/documents/tests/test_create_transcriptions.py
+++ b/arkindex/documents/tests/test_create_transcriptions.py
@@ -43,7 +43,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
 
     def test_write_right(self):
         self.client.force_login(self.private_read_user)
-        with self.assertNumQueries(7):
+        with self.assertNumQueries(6):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.private_page.id}),
                 format='json',
@@ -76,7 +76,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
 
     def test_manual(self):
         self.client.force_login(self.user)
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(7):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -104,7 +104,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         """
         self.client.force_login(self.user)
         ts = self.line.transcriptions.create(text='GLOUBIBOULGA')
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(7):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -123,7 +123,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         Check that a transcription is created with the specified orientation
         """
         self.client.force_login(self.user)
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(7):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -147,7 +147,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         Specifying an invalid text-orientation causes an error
         """
         self.client.force_login(self.user)
-        with self.assertNumQueries(7):
+        with self.assertNumQueries(6):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -158,7 +158,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
     @override_settings(ARKINDEX_FEATURES={'search': False})
     def test_no_search(self):
         self.client.force_login(self.user)
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(7):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -168,7 +168,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
 
     def test_worker_version(self):
         self.client.force_login(self.user)
-        with self.assertNumQueries(7):
+        with self.assertNumQueries(6):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -189,7 +189,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         """
         self.client.force_login(self.user)
 
-        with self.assertNumQueries(9):
+        with self.assertNumQueries(10):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -227,7 +227,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         self.worker_run.process.run()
         task = self.worker_run.process.tasks.first()
 
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(9):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -263,7 +263,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         self.worker_run.process.run()
         task = self.worker_run.process.tasks.first()
 
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(10):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -297,7 +297,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         """
         self.client.force_login(self.superuser)
 
-        with self.assertNumQueries(5):
+        with self.assertNumQueries(4):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -320,7 +320,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         worker_run = self.user.processes.get(mode=ProcessMode.Local).worker_runs.first()
         self.client.force_login(self.superuser)
 
-        with self.assertNumQueries(5):
+        with self.assertNumQueries(4):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -349,7 +349,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         self.worker_run.process.run()
         task = self.worker_run.process.tasks.first()
 
-        with self.assertNumQueries(7):
+        with self.assertNumQueries(6):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -368,7 +368,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
 
     def test_worker_run_not_found(self):
         self.client.force_login(self.user)
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(7):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -386,7 +386,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
 
     def test_worker_run_required_confidence(self):
         self.client.force_login(self.user)
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(7):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -402,7 +402,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
 
     def test_worker_version_xor_worker_run(self):
         self.client.force_login(self.user)
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(7):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',
@@ -424,7 +424,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         null_zone_page = self.corpus.elements.create(type=self.page.type)
 
         self.client.force_login(self.user)
-        with self.assertNumQueries(8):
+        with self.assertNumQueries(7):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': null_zone_page.id}),
                 format='json',
@@ -450,7 +450,7 @@ class TestTranscriptionCreate(FixtureAPITestCase):
         """
         self.client.force_login(self.user)
 
-        with self.assertNumQueries(9):
+        with self.assertNumQueries(10):
             response = self.client.post(
                 reverse('api:transcription-create', kwargs={'pk': self.line.id}),
                 format='json',