diff --git a/app/api/network.py b/app/api/network.py
index 144d5c5bac1993de22c865ea1f2126f3725927ec..ee16cd0c9fa620efc1525c5c8d5955cd10dce16b 100644
--- a/app/api/network.py
+++ b/app/api/network.py
@@ -97,6 +97,42 @@ def create_network():
     )
 
 
+@bp.route("/networks/<int:network_id>", methods=["PATCH"])
+@login_groups_accepted("admin")
+def patch_network(network_id):
+    r"""Patch an existing network
+
+    .. :quickref: Network; Update an existing network
+
+    :param network_id: network primary key
+    :jsonparam vlan_name: vlan name
+    :jsonparam address: vlan address
+    :jsonparam first_ip: first IP of the allowed range
+    :jsonparam last_ip: last IP of the allowed range
+    :jsonparam gateway: gateway IP
+    :jsonparam domain: domain name
+    :jsonparam admin_only: boolean to restrict the network to admin users
+    :type admin_only: bool
+    :jsonparam sensitive: hide the network and all hosts if True (for non admin)
+    :type sensitive: bool
+    :jsonparam description: description
+    """
+    # The method currently doesn't allow to update the network_scope
+    # as this will have an impact on the address
+    allowed_fields = (
+        ("vlan_name", str, None),
+        ("address", str, None),
+        ("first_ip", str, None),
+        ("last_ip", str, None),
+        ("gateway", str, None),
+        ("domain", models.Domain, "name"),
+        ("admin_only", bool, None),
+        ("sensitive", bool, None),
+        ("description", str, None),
+    )
+    return utils.update_generic_model(models.Network, network_id, allowed_fields)
+
+
 @bp.route("/interfaces")
 @login_required
 def get_interfaces():
diff --git a/tests/functional/test_api.py b/tests/functional/test_api.py
index ce9be1455d201c4463626889bed9422588f8aeef..324645edaf229b86249fd62496b04011df6a41ac 100644
--- a/tests/functional/test_api.py
+++ b/tests/functional/test_api.py
@@ -2498,3 +2498,72 @@ def test_patch_interface_new_network_permission(
         token=user_token,
     )
     assert response.status_code == 200
+
+
+def test_patch_network_no_data(client, network_factory, admin_token):
+    network = network_factory()
+    response = patch(
+        client, f"{API_URL}/network/networks/{network.id}", data={}, token=admin_token
+    )
+    check_response_message(response, "At least one field is required", 422)
+
+
+@pytest.mark.parametrize("field,value", [("foo", "xxxx"), ("name", "mynetwork")])
+def test_patch_network_invalid_fields(
+    client, network_factory, admin_token, field, value
+):
+    network = network_factory()
+    response = patch(
+        client,
+        f"{API_URL}/network/networks/{network.id}",
+        data={field: value},
+        token=admin_token,
+    )
+    check_response_message(response, f"Invalid field '{field}'", 422)
+
+
+@pytest.mark.parametrize(
+    "field,value",
+    [
+        ("vlan_name", "new-name"),
+        ("description", "This is a test"),
+        ("admin_only", True),
+        ("sensitive", False),
+        ("sensitive", True),
+    ],
+)
+def test_patch_network(client, network_factory, admin_token, field, value):
+    network = network_factory()
+    data = {field: value}
+    response = patch(
+        client, f"{API_URL}/network/networks/{network.id}", data=data, token=admin_token
+    )
+    assert response.status_code == 200
+    assert response.get_json()[field] == value
+    updated_network = models.Network.query.get(network.id)
+    if isinstance(value, bool):
+        assert getattr(updated_network, field) is value
+    else:
+        assert getattr(updated_network, field) == value
+
+
+def test_patch_network_domain(client, network_factory, domain_factory, admin_token):
+    network = network_factory()
+    domain = domain_factory(name="foo.example.org")
+    data = {"domain": domain.name}
+    response = patch(
+        client, f"{API_URL}/network/networks/{network.id}", data=data, token=admin_token
+    )
+    assert response.status_code == 200
+    assert response.get_json()["domain"] == domain.name
+    updated_network = models.Network.query.get(network.id)
+    assert updated_network.domain == domain
+
+
+def test_patch_network_invalid_domain(client, network_factory, admin_token):
+    network = network_factory()
+    data = {"domain": "foo"}
+    response = patch(
+        client, f"{API_URL}/network/networks/{network.id}", data=data, token=admin_token
+    )
+    check_response_message(response, f"foo is not a valid domain", 400)