diff --git a/src/linkahead/common/models.py b/src/linkahead/common/models.py
index ea537ffe8c44a7a7fb79c2d4080b63f9b3da2284..9085c8e4d9b95c6b71ea66951342960f8b934793 100644
--- a/src/linkahead/common/models.py
+++ b/src/linkahead/common/models.py
@@ -4,9 +4,10 @@
 #
 # Copyright (C) 2018 Research Group Biomedical Physics,
 # Max-Planck-Institute for Dynamics and Self-Organization Göttingen
-# Copyright (C) 2020-2023 Indiscale GmbH <info@indiscale.com>
+# Copyright (C) 2020-2024 IndiScale GmbH <info@indiscale.com>
 # Copyright (C) 2020-2023 Florian Spreckelsen <f.spreckelsen@indiscale.com>
 # Copyright (C) 2020-2022 Timm Fitschen <t.fitschen@indiscale.com>
+# Copyright (C) 2024 Joscha Schmiedt <joscha@schmiedt.dev>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -34,6 +35,7 @@ transactions.
 
 from __future__ import annotations  # Can be removed with 3.10.
 from __future__ import print_function, unicode_literals
+from enum import Enum
 
 import re
 import sys
@@ -45,7 +47,11 @@ from os import listdir
 from os.path import isdir
 from random import randint
 from tempfile import NamedTemporaryFile
-from typing import Any, Optional
+from typing import Any, Literal, Optional, Type, Union, TYPE_CHECKING, List
+
+if TYPE_CHECKING:
+    from datetime import datetime
+
 from warnings import warn
 
 from lxml import etree
@@ -71,13 +77,23 @@ from .versioning import Version
 
 _ENTITY_URI_SEGMENT = "Entity"
 
+
 # importances/inheritance
-OBLIGATORY = "OBLIGATORY"
-SUGGESTED = "SUGGESTED"
-RECOMMENDED = "RECOMMENDED"
-FIX = "FIX"
-ALL = "ALL"
-NONE = "NONE"
+class Inheritance(Enum):
+    OBLIGATORY = "OBLIGATORY"
+    SUGGESTED = "SUGGESTED"
+    RECOMMENDED = "RECOMMENDED"
+    FIX = "FIX"
+    ALL = "ALL"
+    NONE = "NONE"
+
+
+OBLIGATORY = Inheritance.OBLIGATORY
+SUGGESTED = Inheritance.SUGGESTED
+RECOMMENDED = Inheritance.RECOMMENDED
+FIX = Inheritance.FIX
+ALL = Inheritance.ALL
+NONE = Inheritance.NONE
 
 
 SPECIAL_ATTRIBUTES = ["name", "role", "datatype", "description",
@@ -97,8 +113,16 @@ class Entity:
     by the user to control several server-side plug-ins.
     """
 
-    def __init__(self, name=None, id=None, description=None,  # @ReservedAssignment
-                 datatype=None, value=None, **kwargs):
+    def __init__(
+        self,
+        name: Optional[str] = None,
+        id: Optional[int] = None,
+        description: Optional[str] = None,  # @ReservedAssignment
+        datatype: Optional[str] = None,
+        value=None,
+        **kwargs,
+    ):
+
         self.__role = kwargs["role"] if "role" in kwargs else None
         self._checksum = None
         self._size = None
@@ -119,7 +143,7 @@ class Entity:
         self.path = None
         self.file = None
         self.unit = None
-        self.acl = None
+        self.acl: Optional[ACL] = None
         self.permissions = None
         self.is_valid = lambda: False
         self.is_deleted = lambda: False
@@ -323,8 +347,15 @@ class Entity:
     def pickup(self, new_pickup):
         self.__pickup = new_pickup
 
-    def grant(self, realm=None, username=None, role=None,
-              permission=None, priority=False, revoke_denial=True):
+    def grant(
+        self,
+        realm: Optional[str] = None,
+        username: Optional[str] = None,
+        role: Optional[str] = None,
+        permission: str = None,
+        priority: bool = False,
+        revoke_denial: bool = True,
+    ):
         """Grant a permission to a user or role for this entity.
 
         You must specify either only the username and the realm, or only the
@@ -518,8 +549,29 @@ class Entity:
 
         return self
 
-    def add_property(self, property=None, value=None, id=None, name=None, description=None, datatype=None,
-                     unit=None, importance=None, inheritance=None):  # @ReservedAssignment
+    def add_property(
+        self,
+        property: Union[int, str, Entity, None] = None,
+        value: Union[
+            int,
+            str,
+            bool,
+            datetime,
+            Entity,
+            List[int],
+            List[str],
+            List[bool],
+            List[Entity],
+            None,
+        ] = None,
+        id: Optional[int] = None,
+        name: Optional[str] = None,
+        description: Optional[str] = None,
+        datatype: Optional[str] = None,
+        unit: Optional[str] = None,
+        importance: Optional[str] = None,
+        inheritance: Union[str, Inheritance, None] = None,
+    ) -> Entity:  # @ReservedAssignment
         """Add a property to this entity.
 
         The first parameter is meant to identify the property entity either via
@@ -689,7 +741,13 @@ class Entity:
 
         return self
 
-    def add_parent(self, parent=None, id=None, name=None, inheritance=None):  # @ReservedAssignment
+    def add_parent(
+        self,
+        parent: Union[Entity, int, str, None] = None,
+        id: Optional[int] = None,
+        name: Optional[str] = None,
+        inheritance: Union[str, Inheritance, None] = None,
+    ):  # @ReservedAssignment
         """Add a parent to this entity.
 
         Parameters
@@ -703,7 +761,7 @@ class Entity:
         name : str
             Name of the parent entity. Ignored if `parent is not
             none`.
-        inheritance : str
+        inheritance : str, Inheritance
             One of ``obligatory``, ``recommended``, ``suggested``, or ``fix``. Specifies the
             minimum importance which parent properties need to have to be inherited by this
             entity. If no `inheritance` is given, no properties will be inherited by the child.
@@ -810,7 +868,7 @@ out: bool
 
         return self.parents
 
-    def get_parents_recursively(self, retrieve: bool = True):
+    def get_parents_recursively(self, retrieve: bool = True) -> List[Entity]:
         """Get all ancestors of this entity.
 
 Parameters
@@ -825,12 +883,12 @@ out: List[Entity]
   The parents of this Entity
 """
 
-        all_parents = []
+        all_parents: List[Entity] = []
         self._get_parent_recursively(all_parents, retrieve=retrieve)
 
         return all_parents
 
-    def _get_parent_recursively(self, all_parents: list, retrieve: bool = True):
+    def _get_parent_recursively(self, all_parents: List[Entity], retrieve: bool = True):
         """Get all ancestors with a little helper.
 
         As a side effect of this method, the ancestors are added to
@@ -861,7 +919,7 @@ out: List[Entity]
                 all_parents.append(w_parent)
                 w_parent._get_parent_recursively(all_parents, retrieve=retrieve)
 
-    def get_parent(self, key):
+    def get_parent(self, key: Union[int, Entity, str]) -> Union[Entity, None]:
         """Return the first parent matching the key or None if no match exists.
 
         Parameters
@@ -1393,8 +1451,14 @@ out: List[Entity]
         return Container().append(self).retrieve(
             unique=unique, raise_exception_on_error=raise_exception_on_error, flags=flags)
 
-    def insert(self, raise_exception_on_error=True, unique=True,
-               sync=True, strict=False, flags=None):
+    def insert(
+        self,
+        raise_exception_on_error=True,
+        unique=True,
+        sync=True,
+        strict=False,
+        flags: Optional[dict] = None,
+    ):
         """Insert this entity into a LinkAhead server. A successful insertion will
         generate a new persistent ID for this entity. This entity can be
         identified, retrieved, updated, and deleted via this ID until it has
@@ -1877,7 +1941,13 @@ class Property(Entity):
 
 class Message(object):
 
-    def __init__(self, type=None, code=None, description=None, body=None):  # @ReservedAssignment
+    def __init__(
+        self,
+        type: Optional[str] = None,
+        code: Optional[int] = None,
+        description=None,
+        body: str = None,
+    ):  # @ReservedAssignment
         self.description = description
         self.type = type if type is not None else "Info"
         self.code = int(code) if code is not None else None
@@ -1925,7 +1995,7 @@ class RecordType(Entity):
             property=property, id=id, name=name, description=description, datatype=datatype,
             value=value, unit=unit, importance=importance, inheritance=inheritance)
 
-    def add_parent(self, parent=None,  id=None, name=None, inheritance=OBLIGATORY):
+    def add_parent(self, parent=None,  id=None, name=None, inheritance:Union[str, Inheritance]=OBLIGATORY):
         """Add a parent to this RecordType
 
         Parameters
@@ -4692,7 +4762,7 @@ class Permissions():
         return str(self._perms)
 
 
-def parse_xml(xml):
+def parse_xml(xml: Union[str, etree._Element]):
     """parse a string or tree representation of an xml document to a set of
     entities (records, recordtypes, properties, or files).
 
@@ -4701,9 +4771,9 @@ def parse_xml(xml):
     """
 
     if isinstance(xml, etree._Element):
-        elem = xml
+        elem: etree._Element = xml
     else:
-        elem = etree.fromstring(xml)
+        elem: etree._Element = etree.fromstring(xml)
 
     return _parse_single_xml_element(elem)
 
@@ -4762,7 +4832,7 @@ def _parse_single_xml_element(elem):
             "code"), description=elem.get("description"), body=elem.text)
 
 
-def _evaluate_and_add_error(parent_error, ent):
+def _evaluate_and_add_error(parent_error: TransactionError, ent: Entity):
     """Evaluate the error message(s) attached to entity and add a
     corresponding exception to parent_error.
 
@@ -4865,7 +4935,7 @@ def _evaluate_and_add_error(parent_error, ent):
     return parent_error
 
 
-def raise_errors(arg0):
+def raise_errors(arg0: Union[Entity, QueryTemplate, Container]):
     """Raise a TransactionError depending on the error code(s) inside
     Entity, QueryTemplate or Container arg0. More detailed errors may
     be attached to the TransactionError depending on the contents of
@@ -4892,7 +4962,7 @@ def raise_errors(arg0):
         raise transaction_error
 
 
-def delete(ids, raise_exception_on_error=True):
+def delete(ids:Union[List[int], range], raise_exception_on_error=True):
     c = Container()
 
     if isinstance(ids, list) or isinstance(ids, range):