diff --git a/swh/model/model.py b/swh/model/model.py
index a4387016c575c1626dc43cafb26f9616c4bf6afb..d111194799169c2b9a17712094436c0670ad130a 100644
--- a/swh/model/model.py
+++ b/swh/model/model.py
@@ -21,15 +21,14 @@ from .identifiers import (
     directory_identifier,
     normalize_timestamp,
     origin_identifier,
-    parse_swhid,
     release_identifier,
     revision_identifier,
     snapshot_identifier,
 )
+from .identifiers import CoreSWHID
 from .identifiers import ExtendedObjectType as SwhidExtendedObjectType
 from .identifiers import ExtendedSWHID
 from .identifiers import ObjectType as SwhidObjectType
-from .identifiers import SWHID, CoreSWHID
 
 
 class MissingData(Exception):
@@ -67,7 +66,7 @@ def dictify(value):
     "Helper function used by BaseModel.to_dict()"
     if isinstance(value, BaseModel):
         return value.to_dict()
-    elif isinstance(value, (SWHID, ExtendedSWHID)):
+    elif isinstance(value, (CoreSWHID, ExtendedSWHID)):
         return str(value)
     elif isinstance(value, Enum):
         return value.value
@@ -900,11 +899,19 @@ class RawExtrinsicMetadata(BaseModel):
     # context
     origin = attr.ib(type=Optional[str], default=None, validator=type_validator())
     visit = attr.ib(type=Optional[int], default=None, validator=type_validator())
-    snapshot = attr.ib(type=Optional[SWHID], default=None, validator=type_validator())
-    release = attr.ib(type=Optional[SWHID], default=None, validator=type_validator())
-    revision = attr.ib(type=Optional[SWHID], default=None, validator=type_validator())
+    snapshot = attr.ib(
+        type=Optional[CoreSWHID], default=None, validator=type_validator()
+    )
+    release = attr.ib(
+        type=Optional[CoreSWHID], default=None, validator=type_validator()
+    )
+    revision = attr.ib(
+        type=Optional[CoreSWHID], default=None, validator=type_validator()
+    )
     path = attr.ib(type=Optional[bytes], default=None, validator=type_validator())
-    directory = attr.ib(type=Optional[SWHID], default=None, validator=type_validator())
+    directory = attr.ib(
+        type=Optional[CoreSWHID], default=None, validator=type_validator()
+    )
 
     @discovery_date.validator
     def check_discovery_date(self, attribute, value):
@@ -976,7 +983,7 @@ class RawExtrinsicMetadata(BaseModel):
                 f"{self.target.object_type.name.lower()} object: {value}"
             )
 
-        self._check_swhid("snapshot", value)
+        self._check_swhid(SwhidObjectType.SNAPSHOT, value)
 
     @release.validator
     def check_release(self, attribute, value):
@@ -993,7 +1000,7 @@ class RawExtrinsicMetadata(BaseModel):
                 f"{self.target.object_type.name.lower()} object: {value}"
             )
 
-        self._check_swhid("release", value)
+        self._check_swhid(SwhidObjectType.RELEASE, value)
 
     @revision.validator
     def check_revision(self, attribute, value):
@@ -1009,7 +1016,7 @@ class RawExtrinsicMetadata(BaseModel):
                 f"{self.target.object_type.name.lower()} object: {value}"
             )
 
-        self._check_swhid("revision", value)
+        self._check_swhid(SwhidObjectType.REVISION, value)
 
     @path.validator
     def check_path(self, attribute, value):
@@ -1036,7 +1043,7 @@ class RawExtrinsicMetadata(BaseModel):
                 f"{self.target.object_type.name.lower()} object: {value}"
             )
 
-        self._check_swhid("directory", value)
+        self._check_swhid(SwhidObjectType.DIRECTORY, value)
 
     def _check_swhid(self, expected_object_type, swhid):
         if isinstance(swhid, str):
@@ -1044,13 +1051,10 @@ class RawExtrinsicMetadata(BaseModel):
 
         if swhid.object_type != expected_object_type:
             raise ValueError(
-                f"Expected SWHID type '{expected_object_type}', "
-                f"got '{swhid.object_type}' in {swhid}"
+                f"Expected SWHID type '{expected_object_type.name.lower()}', "
+                f"got '{swhid.object_type.name.lower()}' in {swhid}"
             )
 
-        if swhid.metadata:
-            raise ValueError(f"Expected core SWHID, but got: {swhid}")
-
     def to_dict(self):
         d = super().to_dict()
 
@@ -1080,7 +1084,7 @@ class RawExtrinsicMetadata(BaseModel):
         swhid_keys = ("snapshot", "release", "revision", "directory")
         for swhid_key in swhid_keys:
             if d.get(swhid_key):
-                d[swhid_key] = parse_swhid(d[swhid_key])
+                d[swhid_key] = CoreSWHID.from_string(d[swhid_key])
 
         return super().from_dict(d)
 
diff --git a/swh/model/tests/test_model.py b/swh/model/tests/test_model.py
index 5dd61db8bd3fb47afcfa2620dd3cdcb15ef08a40..bb554636808e158bdee35fdc9ef2095b8fa7b174 100644
--- a/swh/model/tests/test_model.py
+++ b/swh/model/tests/test_model.py
@@ -15,8 +15,9 @@ import pytest
 from swh.model.hashutil import MultiHash, hash_to_bytes, hash_to_hex
 import swh.model.hypothesis_strategies as strategies
 from swh.model.identifiers import (
-    SWHID,
+    CoreSWHID,
     ExtendedSWHID,
+    ObjectType,
     content_identifier,
     directory_identifier,
     origin_identifier,
@@ -53,6 +54,8 @@ from swh.model.tests.test_identifiers import (
     snapshot_example,
 )
 
+EXAMPLE_HASH = hash_to_bytes("94a9ed024d3859793618152ea559a168bbcbb5e2")
+
 
 @given(strategies.objects())
 def test_todict_inverse_fromdict(objtype_and_obj):
@@ -861,6 +864,30 @@ def test_metadata_to_dict():
     }
     assert RawExtrinsicMetadata.from_dict(m.to_dict()) == m
 
+    hash_hex = "6162" * 10
+    hash_bin = b"ab" * 10
+    m = RawExtrinsicMetadata(
+        target=_content_swhid,
+        **_common_metadata_fields,
+        origin="https://example.org/",
+        snapshot=CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=hash_bin),
+        release=CoreSWHID(object_type=ObjectType.RELEASE, object_id=hash_bin),
+        revision=CoreSWHID(object_type=ObjectType.REVISION, object_id=hash_bin),
+        path=b"/foo/bar",
+        directory=CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=hash_bin),
+    )
+    assert m.to_dict() == {
+        "target": "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2",
+        **common_fields,
+        "origin": "https://example.org/",
+        "snapshot": f"swh:1:snp:{hash_hex}",
+        "release": f"swh:1:rel:{hash_hex}",
+        "revision": f"swh:1:rev:{hash_hex}",
+        "path": b"/foo/bar",
+        "directory": f"swh:1:dir:{hash_hex}",
+    }
+    assert RawExtrinsicMetadata.from_dict(m.to_dict()) == m
+
 
 def test_metadata_invalid_target():
     """Checks various invalid values for the 'target' field."""
@@ -946,9 +973,8 @@ def test_metadata_validate_context_snapshot():
     ):
         RawExtrinsicMetadata(
             target=_origin_swhid,
-            snapshot=SWHID(
-                object_type="snapshot",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
+            snapshot=CoreSWHID(
+                object_type=ObjectType.SNAPSHOT, object_id=EXAMPLE_HASH,
             ),
             **_common_metadata_fields,
         )
@@ -956,34 +982,17 @@ def test_metadata_validate_context_snapshot():
     # but content can
     RawExtrinsicMetadata(
         target=_content_swhid,
-        snapshot=SWHID(
-            object_type="snapshot", object_id="94a9ed024d3859793618152ea559a168bbcbb5e2"
-        ),
+        snapshot=CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=EXAMPLE_HASH),
         **_common_metadata_fields,
     )
 
-    # Non-core SWHID
-    with pytest.raises(ValueError, match="Expected core SWHID"):
-        RawExtrinsicMetadata(
-            target=_content_swhid,
-            snapshot=SWHID(
-                object_type="snapshot",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-                metadata=_dummy_qualifiers,
-            ),
-            **_common_metadata_fields,
-        )
-
     # SWHID type doesn't match the expected type of this context key
     with pytest.raises(
         ValueError, match="Expected SWHID type 'snapshot', got 'content'"
     ):
         RawExtrinsicMetadata(
             target=_content_swhid,
-            snapshot=SWHID(
-                object_type="content",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-            ),
+            snapshot=CoreSWHID(object_type=ObjectType.CONTENT, object_id=EXAMPLE_HASH,),
             **_common_metadata_fields,
         )
 
@@ -997,44 +1006,24 @@ def test_metadata_validate_context_release():
     ):
         RawExtrinsicMetadata(
             target=_origin_swhid,
-            release=SWHID(
-                object_type="release",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-            ),
+            release=CoreSWHID(object_type=ObjectType.RELEASE, object_id=EXAMPLE_HASH,),
             **_common_metadata_fields,
         )
 
     # but content can
     RawExtrinsicMetadata(
         target=_content_swhid,
-        release=SWHID(
-            object_type="release", object_id="94a9ed024d3859793618152ea559a168bbcbb5e2"
-        ),
+        release=CoreSWHID(object_type=ObjectType.RELEASE, object_id=EXAMPLE_HASH),
         **_common_metadata_fields,
     )
 
-    # Non-core SWHID
-    with pytest.raises(ValueError, match="Expected core SWHID"):
-        RawExtrinsicMetadata(
-            target=_content_swhid,
-            release=SWHID(
-                object_type="release",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-                metadata=_dummy_qualifiers,
-            ),
-            **_common_metadata_fields,
-        )
-
     # SWHID type doesn't match the expected type of this context key
     with pytest.raises(
         ValueError, match="Expected SWHID type 'release', got 'content'"
     ):
         RawExtrinsicMetadata(
             target=_content_swhid,
-            release=SWHID(
-                object_type="content",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-            ),
+            release=CoreSWHID(object_type=ObjectType.CONTENT, object_id=EXAMPLE_HASH,),
             **_common_metadata_fields,
         )
 
@@ -1048,9 +1037,8 @@ def test_metadata_validate_context_revision():
     ):
         RawExtrinsicMetadata(
             target=_origin_swhid,
-            revision=SWHID(
-                object_type="revision",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
+            revision=CoreSWHID(
+                object_type=ObjectType.REVISION, object_id=EXAMPLE_HASH,
             ),
             **_common_metadata_fields,
         )
@@ -1058,34 +1046,17 @@ def test_metadata_validate_context_revision():
     # but content can
     RawExtrinsicMetadata(
         target=_content_swhid,
-        revision=SWHID(
-            object_type="revision", object_id="94a9ed024d3859793618152ea559a168bbcbb5e2"
-        ),
+        revision=CoreSWHID(object_type=ObjectType.REVISION, object_id=EXAMPLE_HASH),
         **_common_metadata_fields,
     )
 
-    # Non-core SWHID
-    with pytest.raises(ValueError, match="Expected core SWHID"):
-        RawExtrinsicMetadata(
-            target=_content_swhid,
-            revision=SWHID(
-                object_type="revision",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-                metadata=_dummy_qualifiers,
-            ),
-            **_common_metadata_fields,
-        )
-
     # SWHID type doesn't match the expected type of this context key
     with pytest.raises(
         ValueError, match="Expected SWHID type 'revision', got 'content'"
     ):
         RawExtrinsicMetadata(
             target=_content_swhid,
-            revision=SWHID(
-                object_type="content",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-            ),
+            revision=CoreSWHID(object_type=ObjectType.CONTENT, object_id=EXAMPLE_HASH,),
             **_common_metadata_fields,
         )
 
@@ -1114,9 +1085,8 @@ def test_metadata_validate_context_directory():
     ):
         RawExtrinsicMetadata(
             target=_origin_swhid,
-            directory=SWHID(
-                object_type="directory",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
+            directory=CoreSWHID(
+                object_type=ObjectType.DIRECTORY, object_id=EXAMPLE_HASH,
             ),
             **_common_metadata_fields,
         )
@@ -1124,34 +1094,18 @@ def test_metadata_validate_context_directory():
     # but content can
     RawExtrinsicMetadata(
         target=_content_swhid,
-        directory=SWHID(
-            object_type="directory",
-            object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-        ),
+        directory=CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=EXAMPLE_HASH,),
         **_common_metadata_fields,
     )
 
-    # Non-core SWHID
-    with pytest.raises(ValueError, match="Expected core SWHID"):
-        RawExtrinsicMetadata(
-            target=_content_swhid,
-            directory=SWHID(
-                object_type="directory",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
-                metadata=_dummy_qualifiers,
-            ),
-            **_common_metadata_fields,
-        )
-
     # SWHID type doesn't match the expected type of this context key
     with pytest.raises(
         ValueError, match="Expected SWHID type 'directory', got 'content'"
     ):
         RawExtrinsicMetadata(
             target=_content_swhid,
-            directory=SWHID(
-                object_type="content",
-                object_id="94a9ed024d3859793618152ea559a168bbcbb5e2",
+            directory=CoreSWHID(
+                object_type=ObjectType.CONTENT, object_id=EXAMPLE_HASH,
             ),
             **_common_metadata_fields,
         )