diff --git a/news/uuid.rst b/news/uuid.rst
new file mode 100644
index 00000000..474793f4
--- /dev/null
+++ b/news/uuid.rst
@@ -0,0 +1,23 @@
+**Added:**
+
+* Gettable `id` property to `DiffractionObject`
+
+**Changed:**
+
+* <news item>
+
+**Deprecated:**
+
+* <news item>
+
+**Removed:**
+
+* <news item>
+
+**Fixed:**
+
+* <news item>
+
+**Security:**
+
+* <news item>
diff --git a/src/diffpy/utils/diffraction_objects.py b/src/diffpy/utils/diffraction_objects.py
index 59aac37b..abfd44b0 100644
--- a/src/diffpy/utils/diffraction_objects.py
+++ b/src/diffpy/utils/diffraction_objects.py
@@ -1,4 +1,5 @@
 import datetime
+import uuid
 import warnings
 from copy import deepcopy
 
@@ -53,6 +54,7 @@ def __init__(
         if yarray is None:
             yarray = np.empty(0)
 
+        self._id = uuid.uuid4()
         self.input_data(xarray, yarray, xtype)
 
     def __eq__(self, other):
@@ -205,6 +207,14 @@ def input_xtype(self):
     def input_xtype(self, _):
         raise AttributeError(_setter_wmsg("input_xtype"))
 
+    @property
+    def id(self):
+        return self._id
+
+    @id.setter
+    def id(self, _):
+        raise AttributeError(_setter_wmsg("id"))
+
     def set_angles_from_list(self, angles_list):
         self.angles = angles_list
         self.n_steps = len(angles_list) - 1.0
diff --git a/tests/test_diffraction_objects.py b/tests/test_diffraction_objects.py
index 328bb512..50080550 100644
--- a/tests/test_diffraction_objects.py
+++ b/tests/test_diffraction_objects.py
@@ -1,5 +1,7 @@
 import re
+import uuid
 from pathlib import Path
+from uuid import UUID
 
 import numpy as np
 import pytest
@@ -335,8 +337,8 @@ def test_dump(tmp_path, mocker):
 
 @pytest.mark.parametrize("inputs, expected", tc_params)
 def test_constructor(inputs, expected):
-    actual_do = DiffractionObject(**inputs)
-    diff = DeepDiff(actual_do.__dict__, expected, ignore_order=True, significant_digits=13)
+    actual = DiffractionObject(**inputs).__dict__
+    diff = DeepDiff(actual, expected, ignore_order=True, significant_digits=13, exclude_paths="root['_id']")
     assert diff == {}
 
 
@@ -369,6 +371,29 @@ def test_all_array_setter():
         actual_do.all_arrays = np.empty((4, 4))
 
 
+def test_id_getter():
+    do = DiffractionObject()
+    assert hasattr(do, "id")
+    assert isinstance(do.id, UUID)
+    assert len(str(do.id)) == 36
+
+
+def test_id_getter_with_mock(mocker):
+    mocker.patch.object(DiffractionObject, "id", new_callable=lambda: UUID("d67b19c6-3016-439f-81f7-cf20a04bee87"))
+    do = DiffractionObject()
+    assert do.id == UUID("d67b19c6-3016-439f-81f7-cf20a04bee87")
+
+
+def test_id_setter_error():
+    do = DiffractionObject()
+
+    with pytest.raises(
+        AttributeError,
+        match="Direct modification of attribute 'id' is not allowed. Please use 'input_data' to modify 'id'.",
+    ):
+        do.id = uuid.uuid4()
+
+
 def test_xarray_yarray_length_mismatch():
     with pytest.raises(
         ValueError,
@@ -384,7 +409,7 @@ def test_input_xtype_getter():
     assert do.input_xtype == "tth"
 
 
-def test_input_xtype_setter():
+def test_input_xtype_setter_error():
     do = DiffractionObject(xtype="tth")
 
     # Attempt to directly modify the property