diff --git a/arkindex/documents/api/elements.py b/arkindex/documents/api/elements.py
index e6900c8f4b0d38c110947616afd16a98c3c9a271..1afd478b6f0eb2a2a56d71268d5cfe988a383d13 100644
--- a/arkindex/documents/api/elements.py
+++ b/arkindex/documents/api/elements.py
@@ -1181,6 +1181,10 @@ class CorpusDeleteSelection(SelectionMixin, DestroyAPIView):
     }
 
     def delete(self, request, *args, **kwargs):
+        rights = Corpus.objects.get(id=self.kwargs['pk']).get_acl_rights(request.user)
+        if Right.Admin not in rights:
+            self.permission_denied(request, message='You do not have admin access to delete elements on this corpus.')
+
         selected_elements = self.get_selection(corpus_id=self.kwargs['pk'])
         if not selected_elements.exists():
             raise NotFound
diff --git a/arkindex/documents/tests/test_corpus.py b/arkindex/documents/tests/test_corpus.py
index f64d10e084227220ca02e12644f10afdad94063a..491738b9e6580e8003f7819a8f22d908d5490641 100644
--- a/arkindex/documents/tests/test_corpus.py
+++ b/arkindex/documents/tests/test_corpus.py
@@ -387,3 +387,46 @@ class TestCorpus(FixtureAPITestCase):
             description=f'Deletion of corpus {self.corpus_private.name}',
             user_id=self.user.id,
         ))
+
+    def test_delete_selected_elements_requires_login(self):
+        response = self.client.delete(reverse('api:corpus-delete-selection', kwargs={'pk': self.corpus_private.id}))
+        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+
+    def test_delete_selected_elements_requires_admin_right(self):
+        self.assertNotIn(Right.Admin, self.corpus_private.get_acl_rights(self.user))
+        self.client.force_login(self.user)
+        response = self.client.delete(reverse('api:corpus-delete-selection', kwargs={'pk': self.corpus_private.id}))
+        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+
+    @patch('arkindex.project.triggers.tasks.element_trash.delay')
+    def test_delete_selected_elements(self, delay_mock):
+        act_type, _ = self.corpus_private.types.get_or_create(
+            slug='act',
+            display_name='Act',
+        )
+        act_x = Element.objects.create(
+            type=act_type,
+            corpus=self.corpus_private,
+            name='Act xxx',
+        )
+        Element.objects.create(
+            type=act_type,
+            corpus=self.corpus_private,
+            name='Act yyy',
+        )
+        self.superuser.selected_elements.add(act_x)
+
+        self.client.force_login(self.superuser)
+        with self.assertNumQueries(6):
+            response = self.client.delete(reverse('api:corpus-delete-selection', kwargs={'pk': self.corpus_private.id}))
+            self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
+
+        self.assertEqual(delay_mock.call_count, 1)
+        args, kwargs = delay_mock.call_args
+        self.assertEqual(len(args), 0)
+        self.assertCountEqual(list(kwargs.pop('queryset')), list(Element.objects.filter(id=act_x.id)))
+        self.assertDictEqual(kwargs, {
+            'delete_children': True,
+            'user_id': self.superuser.id,
+            'description': 'Element deletion',
+        })