diff --git a/api-ref/source/baremetal-api-v1-nodes.inc b/api-ref/source/baremetal-api-v1-nodes.inc
index c25f9fa2a5..8c6b4274bc 100644
--- a/api-ref/source/baremetal-api-v1-nodes.inc
+++ b/api-ref/source/baremetal-api-v1-nodes.inc
@@ -326,6 +326,8 @@ Updates the information stored about a Node.
 Note that this endpoint can not be used to request state changes, which are
 managed through sub-resources.
 
+API microversion 1.25 introduced the ability to unset a node's chassis UUID.
+
 Normal response codes: 200
 
 .. TODO: add error codes
diff --git a/doc/source/dev/webapi-version-history.rst b/doc/source/dev/webapi-version-history.rst
index cb284e1b25..a1265a9a34 100644
--- a/doc/source/dev/webapi-version-history.rst
+++ b/doc/source/dev/webapi-version-history.rst
@@ -2,6 +2,10 @@
 REST API Version History
 ========================
 
+**1.25**
+
+    Add possibility to unset chassis_uuid from a node.
+
 **1.24**
 
     Added new endpoints '/v1/nodes/<node>/portgroups' and '/v1/portgroups/<portgroup>/ports'.
diff --git a/ironic/api/controllers/v1/node.py b/ironic/api/controllers/v1/node.py
index d57c5a947f..c14cdcfb00 100644
--- a/ironic/api/controllers/v1/node.py
+++ b/ironic/api/controllers/v1/node.py
@@ -893,8 +893,6 @@ class NodePatchType(types.JsonPatchType):
 
     _api_base = Node
 
-    _extra_non_removable_attrs = {'/chassis_uuid'}
-
     @staticmethod
     def internal_attrs():
         defaults = types.JsonPatchType.internal_attrs()
@@ -1192,7 +1190,17 @@ class NodesController(rest.RestController):
             try:
                 patch_val = getattr(node, field)
             except AttributeError:
-                # Ignore fields that aren't exposed in the API
+                # Ignore fields that aren't exposed in the API, except
+                # chassis_id. chassis_id would have been set (instead of
+                # chassis_uuid) if the node belongs to a chassis. This
+                # AttributeError is raised for chassis_id only if
+                # 1. the node doesn't belong to a chassis or
+                # 2. the node belonged to a chassis but is now being removed
+                # from the chassis.
+                if (field == "chassis_id" and rpc_node[field] is not None):
+                    if not api_utils.allow_remove_chassis_uuid():
+                        raise exception.NotAcceptable()
+                    rpc_node[field] = None
                 continue
             if patch_val == wtypes.Unset:
                 patch_val = None
diff --git a/ironic/api/controllers/v1/utils.py b/ironic/api/controllers/v1/utils.py
index 91ead315cf..832f7f8a95 100644
--- a/ironic/api/controllers/v1/utils.py
+++ b/ironic/api/controllers/v1/utils.py
@@ -432,6 +432,16 @@ def allow_portgroups_subcontrollers():
             versions.MINOR_24_PORTGROUPS_SUBCONTROLLERS)
 
 
+def allow_remove_chassis_uuid():
+    """Check if chassis_uuid can be removed from node.
+
+    Version 1.25 of the API added support for chassis_uuid
+    removal
+    """
+    return (pecan.request.version.minor >=
+            versions.MINOR_25_UNSET_CHASSIS_UUID)
+
+
 def get_controller_reserved_names(cls):
     """Get reserved names for a given controller.
 
diff --git a/ironic/api/controllers/v1/versions.py b/ironic/api/controllers/v1/versions.py
index 82635e4d06..a029b22c7d 100644
--- a/ironic/api/controllers/v1/versions.py
+++ b/ironic/api/controllers/v1/versions.py
@@ -55,6 +55,7 @@ BASE_VERSION = 1
 # v1.23: Add portgroup support.
 # v1.24: Add subcontrollers: node.portgroup, portgroup.ports.
 #        Add port.portgroup_uuid field.
+# v1.25: Add possibility to unset chassis_uuid from node.
 
 MINOR_0_JUNO = 0
 MINOR_1_INITIAL_VERSION = 1
@@ -81,11 +82,12 @@ MINOR_21_RESOURCE_CLASS = 21
 MINOR_22_LOOKUP_HEARTBEAT = 22
 MINOR_23_PORTGROUPS = 23
 MINOR_24_PORTGROUPS_SUBCONTROLLERS = 24
+MINOR_25_UNSET_CHASSIS_UUID = 25
 
 # When adding another version, update MINOR_MAX_VERSION and also update
 # doc/source/dev/webapi-version-history.rst with a detailed explanation of
 # what the version has changed.
-MINOR_MAX_VERSION = MINOR_24_PORTGROUPS_SUBCONTROLLERS
+MINOR_MAX_VERSION = MINOR_25_UNSET_CHASSIS_UUID
 
 # String representations of the minor and maximum versions
 MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_1_INITIAL_VERSION)
diff --git a/ironic/tests/unit/api/v1/test_nodes.py b/ironic/tests/unit/api/v1/test_nodes.py
index b99deec315..917a952470 100644
--- a/ironic/tests/unit/api/v1/test_nodes.py
+++ b/ironic/tests/unit/api/v1/test_nodes.py
@@ -32,6 +32,7 @@ from ironic.api.controllers import base as api_base
 from ironic.api.controllers import v1 as api_v1
 from ironic.api.controllers.v1 import node as api_node
 from ironic.api.controllers.v1 import utils as api_utils
+from ironic.api.controllers.v1 import versions
 from ironic.common import boot_devices
 from ironic.common import exception
 from ironic.common import states
@@ -1317,6 +1318,40 @@ class TestPatch(test_api_base.BaseApiTest):
         self.assertEqual('application/json', response.content_type)
         self.assertEqual(http_client.OK, response.status_code)
 
+    def test_remove_chassis_uuid(self):
+        self.mock_update_node.return_value = self.node
+        headers = {api_base.Version.string: "1.25"}
+        response = self.patch_json('/nodes/%s' % self.node.uuid,
+                                   [{'path': '/chassis_uuid',
+                                     'op': 'remove'}],
+                                   headers=headers)
+        self.assertEqual('application/json', response.content_type)
+        self.assertEqual(http_client.OK, response.status_code)
+
+    def test_remove_chassis_uuid_invalid_api_version(self):
+        self.mock_update_node.return_value = self.node
+        headers = {api_base.Version.string: "1.24"}
+        response = self.patch_json('/nodes/%s' % self.node.uuid,
+                                   [{'path': '/chassis_uuid',
+                                     'op': 'remove'}],
+                                   headers=headers,
+                                   expect_errors=True)
+        self.assertEqual('application/json', response.content_type)
+        self.assertEqual(http_client.NOT_ACCEPTABLE, response.status_code)
+        self.assertTrue(response.json['error_message'])
+
+    @mock.patch("pecan.request")
+    def test__update_changed_fields_remove_chassis_uuid(self, mock_pecan_req):
+        mock_pecan_req.version.minor = versions.MINOR_MAX_VERSION
+        controller = api_node.NodesController()
+
+        node_dict = self.node.as_dict()
+        del node_dict['chassis_id']
+        node_no_chassis = api_node.Node(**node_dict)
+
+        controller._update_changed_fields(node_no_chassis, self.node)
+        self.assertIsNone(self.node.chassis_id)
+
     def test_add_chassis_id(self):
         response = self.patch_json('/nodes/%s' % self.node.uuid,
                                    [{'path': '/chassis_id',
diff --git a/ironic/tests/unit/api/v1/test_utils.py b/ironic/tests/unit/api/v1/test_utils.py
index 5e507ff54d..a6bfc59b2d 100644
--- a/ironic/tests/unit/api/v1/test_utils.py
+++ b/ironic/tests/unit/api/v1/test_utils.py
@@ -299,6 +299,13 @@ class TestApiUtils(base.TestCase):
         mock_request.version.minor = 22
         self.assertFalse(utils.allow_portgroups())
 
+    @mock.patch.object(pecan, 'request', spec_set=['version'])
+    def test_allow_remove_chassis_uuid(self, mock_request):
+        mock_request.version.minor = 25
+        self.assertTrue(utils.allow_remove_chassis_uuid())
+        mock_request.version.minor = 24
+        self.assertFalse(utils.allow_remove_chassis_uuid())
+
 
 class TestNodeIdent(base.TestCase):
 
diff --git a/releasenotes/notes/add-chassis_uuid-removal-possibility-8b06341a91f7c676.yaml b/releasenotes/notes/add-chassis_uuid-removal-possibility-8b06341a91f7c676.yaml
new file mode 100644
index 0000000000..aaa591e7cb
--- /dev/null
+++ b/releasenotes/notes/add-chassis_uuid-removal-possibility-8b06341a91f7c676.yaml
@@ -0,0 +1,4 @@
+---
+features:
+  - Adds support for removing the chassis UUID associated with a node (via
+    PATCH /v1/nodes/<ident>). This is available starting with API version 1.25.