diff --git a/Makefile b/Makefile
index 26f5c8182545b2a57b3921f3745d16ff6305a0cc..88fe5405a5d91f8f3bf2cb7659ec25251a6c81aa 100644
--- a/Makefile
+++ b/Makefile
@@ -35,11 +35,15 @@ install:
 unittest:
 	pytest-3 unittests
 
+lint:
+	pylint --unsafe-load-any-extension=y --fail-under=9.72 -d R,C --ignore=swagger_client src/caosadvancedtools
+.PHONY: lint
+
+typing:
+	mypy src unittests
+	mypy integrationtests
+
 style:
 	pycodestyle --count --exclude=swagger_client src unittests
 	autopep8 -ar --diff --exit-code --exclude swagger_client src unittests
 .PHONY: style
-
-lint:
-	pylint --unsafe-load-any-extension=y --fail-under=9.72 -d R,C --ignore=swagger_client src/caosadvancedtools
-.PHONY: lint
diff --git a/setup.cfg b/setup.cfg
index 74c5620b86c6fd5ee96abea95dab4010c9fb87a3..021733bd970adc9d8c80406a21bb3fddc17f05b3 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,2 +1,8 @@
 [pycodestyle]
 ignore=E501,E121,E123,E126,E226,E24,E704,W503,W504
+
+[mypy]
+ignore_missing_imports = True
+exclude = (?x)(
+    /extroot/    # Integration test data
+  )
\ No newline at end of file
diff --git a/src/caosadvancedtools/serverside/examples/example_script.py b/src/caosadvancedtools/serverside/examples/example_script.py
index d97d2d0d1f936b1c12e857d38fce043f0b514340..138354c8077a097c018403680587e49fee35bcf6 100755
--- a/src/caosadvancedtools/serverside/examples/example_script.py
+++ b/src/caosadvancedtools/serverside/examples/example_script.py
@@ -50,7 +50,7 @@ import matplotlib.pyplot as plt
 import numpy as np
 from caosadvancedtools.cfood import assure_property_is
 from caosadvancedtools.crawler import apply_list_of_updates
-from caosadvancedtools.guard import INSERT, UPDATE
+from caosadvancedtools.guard import UPDATE
 from caosadvancedtools.guard import global_guard as guard
 from caosadvancedtools.serverside.helper import send_mail as main_send_mail
 
@@ -62,7 +62,7 @@ logger = logging.getLogger(__name__)
 guard.set_level(level=UPDATE)
 
 
-def send_mail(changes: [db.Entity], receipient: str):
+def send_mail(changes: list[db.Entity], receipient: str):
     """ calls sendmail in order to send a mail to the curator about pending
     changes
 
diff --git a/unittests/table_json_conversion/create_jsonschema.py b/unittests/table_json_conversion/create_jsonschema.py
index 8ab4ad2d973b78522e858b3ee866b870ecf187a4..4efd6bb27448311635cf7cd73565ec117256bb04 100755
--- a/unittests/table_json_conversion/create_jsonschema.py
+++ b/unittests/table_json_conversion/create_jsonschema.py
@@ -24,6 +24,7 @@ from __future__ import annotations
 
 import argparse
 import json
+from typing import Optional
 
 import caosadvancedtools.json_schema_exporter as jsex
 from caosadvancedtools.models import parser
@@ -31,7 +32,7 @@ from caosadvancedtools.models import parser
 
 
 def prepare_datamodel(modelfile, recordtypes: list[str], outfile: str,
-                      do_not_create: list[str] = None):
+                      do_not_create: Optional[list[str]] = None):
     if do_not_create is None:
         do_not_create = []
     model = parser.parse_model_from_yaml(modelfile)
diff --git a/unittests/table_json_conversion/test_fill_xlsx.py b/unittests/table_json_conversion/test_fill_xlsx.py
index 899bb81ef1f91f3326f214f49f135a55b97d299f..7e9a79c6cff192e82cca256a49ea7be9ca387a75 100644
--- a/unittests/table_json_conversion/test_fill_xlsx.py
+++ b/unittests/table_json_conversion/test_fill_xlsx.py
@@ -24,6 +24,7 @@ import json
 import os
 import re
 import tempfile
+from typing import Optional
 
 import jsonschema.exceptions as schema_exc
 import pytest
@@ -49,7 +50,7 @@ def rfp(*pathcomponents):
 
 
 def fill_and_compare(json_file: str, template_file: str, known_good: str,
-                     schema: str = None, custom_output: str = None):
+                     schema: Optional[str] = None, custom_output: Optional[str] = None):
     """Fill the data into a template and compare to a known good.
 
 Parameters:
diff --git a/unittests/table_json_conversion/test_read_xlsx.py b/unittests/table_json_conversion/test_read_xlsx.py
index 0eec2e9caa1f800ad86ab43057b8c512dc09881f..17574d8af4116a1a2318fbf694d41b4033fbfa47 100644
--- a/unittests/table_json_conversion/test_read_xlsx.py
+++ b/unittests/table_json_conversion/test_read_xlsx.py
@@ -20,17 +20,15 @@
 """Testing the conversion from XLSX to JSON"""
 
 
+from .utils import assert_equal_jsons
+from caosadvancedtools.table_json_conversion import convert
+import pytest
 import datetime
 import json
 import os
 import re
-
 from types import SimpleNamespace
-
-import pytest
-from caosadvancedtools.table_json_conversion import convert
-
-from .utils import assert_equal_jsons
+from typing import Optional
 
 
 def rfp(*pathcomponents):
@@ -40,7 +38,7 @@ def rfp(*pathcomponents):
 
 
 def convert_and_compare(xlsx_file: str, schema_file: str, known_good_file: str,
-                        known_good_data: dict = None, strict: bool = False,
+                        known_good_data: Optional[dict] = None, strict: bool = False,
                         validate: bool = True) -> dict:
     """Convert an XLSX file and compare to a known result.
 
diff --git a/unittests/table_json_conversion/test_table_template_generator.py b/unittests/table_json_conversion/test_table_template_generator.py
index d9a84dcf53ec991eec709aab406a7652881e6ea8..24a77ddcc49a68f763bae771a36f8423d6a987a4 100644
--- a/unittests/table_json_conversion/test_table_template_generator.py
+++ b/unittests/table_json_conversion/test_table_template_generator.py
@@ -22,6 +22,7 @@
 import json
 import os
 import tempfile
+from typing import Optional
 
 import pytest
 from caosadvancedtools.table_json_conversion.table_generator import XLSXTemplateGenerator
@@ -39,8 +40,9 @@ def rfp(*pathcomponents):
     return os.path.join(os.path.dirname(__file__), *pathcomponents)
 
 
-def _compare_generated_to_known_good(schema_file: str, known_good: str, foreign_keys: dict = None,
-                                     outfile: str = None) -> tuple:
+def _compare_generated_to_known_good(schema_file: str, known_good: str,
+                                     foreign_keys: Optional[dict] = None,
+                                     outfile: Optional[str] = None) -> tuple:
     """Generate an XLSX from the schema, then compare to known good output.
 
 Returns
diff --git a/unittests/table_json_conversion/utils.py b/unittests/table_json_conversion/utils.py
index b95715f72b08384f75857e48bcba328488313ad5..86f6d95f6d41fe5635b23fe724f62adda389d3db 100644
--- a/unittests/table_json_conversion/utils.py
+++ b/unittests/table_json_conversion/utils.py
@@ -21,13 +21,13 @@
 """Utilities for the tests.
 """
 
-from typing import Iterable, Union
+from typing import Iterable, Optional, Union
 
 from openpyxl import Workbook
 
 
 def assert_equal_jsons(json1, json2, allow_none: bool = True, allow_empty: bool = True,
-                       path: list = None) -> None:
+                       path: Optional[list] = None) -> None:
     """Compare two json objects for near equality.
 
 Raise an assertion exception if they are not equal."""
@@ -100,7 +100,7 @@ hidden: bool, optional
                 )
 
 
-def _is_recursively_none(obj: Union[list, dict] = None):
+def _is_recursively_none(obj: Optional[Union[list, dict]] = None):
     """Test if ``obj`` is None or recursively consists only of None-like objects."""
     if obj is None:
         return True
diff --git a/unittests/test_cfood.py b/unittests/test_cfood.py
index e2f15ffdc7929fbd67aee37bccdb0f44cacef104..3332306aea4f443645393dd3f05fe3e43107fa23 100644
--- a/unittests/test_cfood.py
+++ b/unittests/test_cfood.py
@@ -85,7 +85,7 @@ class SimpleCFood(AbstractFileCFood):
 
 
 class DependendCFood(AbstractCFood):
-    existing = []
+    existing: list[DependendCFood] = []
 
     @classmethod
     def match_item(cls, item):