diff --git a/arkindex/documents/models.py b/arkindex/documents/models.py
index e9d13d9e2d9294f8a3a8d961b709320c94f282f3..dbd019c2abd2ea8cfaf0bfd20d5d2c07cd448e09 100644
--- a/arkindex/documents/models.py
+++ b/arkindex/documents/models.py
@@ -625,6 +625,7 @@ class MetaType(Enum):
     # Element's original structure reference (intended to be indexed)
     Reference = 'reference'
     Numeric = 'numeric'
+    URL = 'url'
 
 
 class AllowedMetaData(models.Model):
diff --git a/arkindex/documents/serializers/elements.py b/arkindex/documents/serializers/elements.py
index 0a6c2a8a1e8733da18bb0a57688ee74f4572f173..1c202d91c06a3c9406a6c6ec2ede9123a5658211 100644
--- a/arkindex/documents/serializers/elements.py
+++ b/arkindex/documents/serializers/elements.py
@@ -4,6 +4,8 @@ from collections import defaultdict
 from uuid import UUID
 
 from django.contrib.gis.geos import LinearRing
+from django.core.exceptions import ValidationError as DjangoValidationError
+from django.core.validators import URLValidator
 from django.db import transaction
 from django.utils.functional import cached_property
 from drf_spectacular.utils import extend_schema_field
@@ -83,6 +85,7 @@ class MetaDataBulkItemSerializer(MetaDataLightSerializer):
         # Those can be None if someone messed up their input; DRF will catch it itself afterwards, so we ignore None.
         meta_type = data.get('type', self.instance.type if self.instance else None)
         value = data.get('value', self.instance.value if self.instance else None)
+
         if meta_type == MetaType.Numeric and value is not None:
             try:
                 # Python allows _ to separate numbers (123_456.789_101), but Postgres does not, so we forbid them.
@@ -94,6 +97,15 @@ class MetaDataBulkItemSerializer(MetaDataLightSerializer):
                 raise serializers.ValidationError({
                     'value': ['The value of a numeric metadata should be a valid floating-point number.']
                 })
+
+        if meta_type == MetaType.URL and value is not None:
+            try:
+                URLValidator(schemes=['http', 'https'])(value)
+            except DjangoValidationError:
+                raise serializers.ValidationError({
+                    'value': ['The value of a URL metadata must be a valid HTTP or HTTPS URL.']
+                })
+
         return data
 
 
diff --git a/arkindex/documents/tests/test_metadata.py b/arkindex/documents/tests/test_metadata.py
index 109ea852bf8ed0cb860342c917451cd7b9db813e..e906d0fb95e011b17e54f5ecc7a9dff7605a59c7 100644
--- a/arkindex/documents/tests/test_metadata.py
+++ b/arkindex/documents/tests/test_metadata.py
@@ -586,6 +586,34 @@ class TestMetaData(FixtureAPITestCase):
         self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
         self.assertDictEqual(response.json(), {'value': ['The value of a numeric metadata should be a valid floating-point number.']})
 
+    def test_create_url_metadata(self):
+        self.client.force_login(self.superuser)
+        response = self.client.post(
+            reverse('api:element-metadata', kwargs={'pk': str(self.vol.id)}),
+            data={'type': 'url', 'name': 'blah', 'value': 'http://nowhere.com'}
+        )
+        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+        md = self.vol.metadatas.get(type=MetaType.URL, name='blah')
+        self.assertEqual(md.value, 'http://nowhere.com')
+
+    def test_create_url_metadata_invalid(self):
+        self.client.force_login(self.superuser)
+        response = self.client.post(
+            reverse('api:element-metadata', kwargs={'pk': str(self.vol.id)}),
+            data={'type': 'url', 'name': 'blah', 'value': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'}
+        )
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertDictEqual(response.json(), {'value': ['The value of a URL metadata must be a valid HTTP or HTTPS URL.']})
+
+    def test_create_url_metadata_scheme(self):
+        self.client.force_login(self.superuser)
+        response = self.client.post(
+            reverse('api:element-metadata', kwargs={'pk': str(self.vol.id)}),
+            data={'type': 'url', 'name': 'blah', 'value': 'git+https://gitlab.com/arkindex/backend.git'}
+        )
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertDictEqual(response.json(), {'value': ['The value of a URL metadata must be a valid HTTP or HTTPS URL.']})
+
     def test_bulk_create_metadata_verified(self):
         response = self.client.post(reverse('api:element-metadata-bulk', kwargs={'pk': str(self.vol.id)}))
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)