diff --git a/arkindex/documents/serializers/elements.py b/arkindex/documents/serializers/elements.py
index 19a09447bb718528eef9eebbbcc569faaf5a1ec2..776711a5de9aea1bef0641e5670207be84d902da 100644
--- a/arkindex/documents/serializers/elements.py
+++ b/arkindex/documents/serializers/elements.py
@@ -172,6 +172,32 @@ class MetaDataBulkSerializer(serializers.Serializer):
         super().__init__(*args, **kwargs)
         self.fields['metadata_list'] = MetaDataBulkItemSerializer(many=True, allow_empty=False, context=self.context)
 
+    def make_metadata_tuples(self, meta_list):
+        tuples_list = []
+        for item in meta_list:
+            item_tuple = (
+                item.get('name'),
+                item.get('type').value,
+                item.get('value')
+            )
+            tuples_list.append(item_tuple)
+        return tuples_list
+
+    def validate(self, data):
+        data = super().validate(data)
+        request_metadata = self.make_metadata_tuples(data['metadata_list'])
+        unique_metadata = set(request_metadata)
+        if len(unique_metadata) != len(request_metadata):
+            raise ValidationError('Metadata in metadata list must make a unique set.')
+        names = [item['name'] for item in data['metadata_list']]
+        types = [item['type'] for item in data['metadata_list']]
+        filtered_metadata = MetaData.objects.filter(element=self.context['element'].id, name__in=names, type__in=types).values()
+        existing_metadata = self.make_metadata_tuples(filtered_metadata)
+        meta_matches = set(request_metadata) & set(existing_metadata)
+        if meta_matches:
+            raise ValidationError(f'Metadata {meta_matches} already exist(s) on this element.')
+        return data
+
     def create(self, validated_data):
         validated_data['metadata_list'] = MetaData.objects.bulk_create([
             MetaData(
diff --git a/arkindex/documents/tests/test_metadata.py b/arkindex/documents/tests/test_metadata.py
index 248dc5efb6ddafa5a448d5b17acf3d356085ef4a..180ee8ccc11f6680ff657e90000c34b94d6a96ed 100644
--- a/arkindex/documents/tests/test_metadata.py
+++ b/arkindex/documents/tests/test_metadata.py
@@ -967,3 +967,45 @@ class TestMetaData(FixtureAPITestCase):
                         {'name': 'not allowed', 'type': MetaType.Location}
                     ]
                 )
+
+    def test_bulk_create_metadata_unique(self):
+        """
+        The metadata created with the bulk endpoint must be unique
+        """
+        self.client.force_login(self.user)
+        with self.assertNumQueries(5):
+            response = self.client.post(
+                reverse('api:element-metadata-bulk', kwargs={'pk': str(self.vol.id)}),
+                data={'metadata_list': [
+                    {'type': 'location', 'name': 'location', 'value': 'Texas'},
+                    {'type': 'location', 'name': 'location', 'value': 'Texas'}
+                ]},
+                format='json'
+            )
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertDictEqual(response.json(), {
+            'non_field_errors': ['Metadata in metadata list must make a unique set.']
+        })
+
+    def test_bulk_create_metadata_no_duplicates(self):
+        """
+        Do not create metadata that already exist on the element
+        """
+        self.client.force_login(self.user)
+        response_1 = self.client.post(
+            reverse('api:element-metadata', kwargs={'pk': str(self.vol.id)}),
+            data={'type': 'location', 'name': 'location', 'value': 'Texas'}
+        )
+        self.assertEqual(response_1.status_code, status.HTTP_201_CREATED)
+        with self.assertNumQueries(4):
+            response_2 = self.client.post(
+                reverse('api:element-metadata-bulk', kwargs={'pk': str(self.vol.id)}),
+                data={'metadata_list': [
+                    {'type': 'location', 'name': 'location', 'value': 'Texas'}
+                ]},
+                format='json'
+            )
+        self.assertEqual(response_2.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertDictEqual(response_2.json(), {
+            'non_field_errors': ["Metadata {('location', 'location', 'Texas')} already exist(s) on this element."]
+        })