diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 1997d1d1952a973e133f25dffd4a0238c35d2091..b1fa8cc75fed438d03a01b4244b4be725ce18884 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -9,6 +9,16 @@ and this project adheres to `Semantic Versioning`_.
 Unreleased
 ----------
 
+Added
+~~~~~
+
+* Plan version can be explicitly selected (defaulting to newest)
+
+Fixed
+~~~~~
+
+* Import now only imports one plan version
+
 `2.1`_ - 2022-01-13
 -------------------
 
diff --git a/README.rst b/README.rst
index 8352cbaf25df4810553075417fac68b9191efa92..d1f6c454c66b982c298bb41668b42f11b308aff0 100644
--- a/README.rst
+++ b/README.rst
@@ -32,7 +32,7 @@ Licence
 
   Copyright © 2018, 2019, 2020, 2021 Jonathan Weth <dev@jonathanweth.de>
   Copyright © 2018, 2019 Frank Poetzsch-Heffter <p-h@katharineum.de>
-  Copyright © 2019, 2020, 2021 Dominik George <dominik.george@teckids.org>
+  Copyright © 2019, 2020, 2021, 2022 Dominik George <dominik.george@teckids.org>
   Copyright © 2019, 2020 Tom Teichler <tom.teichler@teckids.org>
   Copyright © 2019 Julian Leucker <leuckeju@katharineum.de>
   Copyright © 2019 mirabilos <thorsten.glaser@teckids.org>
diff --git a/aleksis/apps/untis/apps.py b/aleksis/apps/untis/apps.py
index 4205a066700754edf9189e3eab8b3299821ff469..27a0a264b2efadb292aeb33c885126a2005088f7 100644
--- a/aleksis/apps/untis/apps.py
+++ b/aleksis/apps/untis/apps.py
@@ -12,7 +12,7 @@ class UntisConfig(AppConfig):
     copyright_info = (
         ([2018, 2019, 2020, 2021], "Jonathan Weth", "dev@jonathanweth.de"),
         ([2018, 2019], "Frank Poetzsch-Heffter", "p-h@katharineum.de"),
-        ([2019, 2020, 2021], "Dominik George", "dominik.george@teckids.org"),
+        ([2019, 2020, 2021, 2022], "Dominik George", "dominik.george@teckids.org"),
         ([2019, 2020], "Tom Teichler", "tom.teichler@teckids.org"),
         ([2019], "Julian Leucker", "leuckeju@katharineum.de"),
         ([2019], "mirabilos", "thorsten.glaser@teckids.org"),
diff --git a/aleksis/apps/untis/commands.py b/aleksis/apps/untis/commands.py
index ce6b17a86b07347468f9a737da16a0868fe4cb48..ae85233596d18b6f63f6c1f9e4434e6709e6ffd6 100644
--- a/aleksis/apps/untis/commands.py
+++ b/aleksis/apps/untis/commands.py
@@ -27,15 +27,15 @@ class ImportCommand:
         return None
 
     @classmethod
-    def run(cls, background: bool = False):
+    def run(cls, background: bool = False, version: Optional[int] = None):
         """Run the import command (foreground/background)."""
         if background:
             from .tasks import TASKS
 
             task = TASKS[cls.task_name]
-            task.delay()
+            task.delay(version=version)
         else:
-            _untis_import_mysql(cls.get_terms())
+            _untis_import_mysql(cls.get_terms(), version=version)
 
 
 class CurrentImportCommand(ImportCommand):
diff --git a/aleksis/apps/untis/management/commands/untis_import_mysql.py b/aleksis/apps/untis/management/commands/untis_import_mysql.py
index a53a9e61b5c6e88fbb45b704d931434e7b51fd60..1aa6bdd6e55a72faebba81bf90dfcfd461256ca5 100644
--- a/aleksis/apps/untis/management/commands/untis_import_mysql.py
+++ b/aleksis/apps/untis/management/commands/untis_import_mysql.py
@@ -13,8 +13,13 @@ class Command(BaseCommand):
             action="store_true",
             help="Run import job in background using Celery",
         )
+        parser.add_argument(
+            "--plan-version",
+            help="Select explicit Untis plan version",
+        )
 
     def handle(self, *args, **options):
         command = COMMANDS_BY_NAME[options["command"]]
         background = options["background"]
-        command.run(background=background)
+        version = options.get("plan_version", None)
+        command.run(background=background, version=version)
diff --git a/aleksis/apps/untis/tasks.py b/aleksis/apps/untis/tasks.py
index 6da6405c5ad00f37dd90a046bf23121993dceb94..3e45b18e2e16bdb7600597c87de7571ee7c514c9 100644
--- a/aleksis/apps/untis/tasks.py
+++ b/aleksis/apps/untis/tasks.py
@@ -6,8 +6,8 @@ TASKS = {}
 for import_command in ImportCommand.__subclasses__():
 
     @app.task(name=import_command.task_name, bind=True)
-    def _task(self):
+    def _task(self, *args, **kwargs):
         import_command = COMMANDS_BY_TASK_NAME[self.name]
-        import_command.run()
+        import_command.run(*args, **kwargs)
 
     TASKS[import_command.task_name] = _task
diff --git a/aleksis/apps/untis/util/mysql/importers/terms.py b/aleksis/apps/untis/util/mysql/importers/terms.py
index e8b662008230d5b5e74e6dc70a9cbfd543bbc59f..092a9f9d990e7056461257afc74cb3c8560ad66b 100644
--- a/aleksis/apps/untis/util/mysql/importers/terms.py
+++ b/aleksis/apps/untis/util/mysql/importers/terms.py
@@ -2,7 +2,7 @@ import logging
 from datetime import date
 from typing import Dict, Optional
 
-from django.db.models import QuerySet
+from django.db.models import Max, OuterRef, QuerySet, Subquery
 from django.utils import timezone
 
 from tqdm import tqdm
@@ -49,12 +49,31 @@ logger = logging.getLogger(__name__)
 
 def import_terms(
     qs: Optional[QuerySet] = None,
+    version: Optional[int] = None,
 ) -> Dict[int, chronos_models.ValidityRange]:
     """Import terms and school years as validity ranges and school terms."""
     ranges_ref = {}
 
     if not isinstance(qs, QuerySet):
-        qs = run_using(mysql_models.Terms.objects).all()
+        qs = run_using(mysql_models.Terms.objects)
+
+    if version is None:
+        # Select newest version per term / validity range
+        sub_qs = (
+            run_using(mysql_models.Terms.objects)
+            .filter(
+                school_id=OuterRef("school_id"),
+                schoolyear_id=OuterRef("schoolyear_id"),
+                term_id=OuterRef("term_id"),
+            )
+            .values("school_id", "schoolyear_id", "term_id")
+            .annotate(max_version=Max("version_id"))
+            .values("max_version")
+        )
+        qs = qs.filter(version_id=Subquery(sub_qs))
+    else:
+        # Select passed version
+        qs = qs.filter(version_id=version)
 
     school_terms = {}
     for term in tqdm(qs, desc="Import terms (as validity ranges)", **TQDM_DEFAULTS):
diff --git a/aleksis/apps/untis/util/mysql/main.py b/aleksis/apps/untis/util/mysql/main.py
index c372de002f96f8d194d2d71326d24b4ddf7891ad..b3e6ca510ced6f8cb0bb1c13803537422501fdaa 100644
--- a/aleksis/apps/untis/util/mysql/main.py
+++ b/aleksis/apps/untis/util/mysql/main.py
@@ -25,9 +25,9 @@ from .importers.lessons import import_lessons
 from .importers.substitutions import import_substitutions
 
 
-def untis_import_mysql(terms: Optional[QuerySet] = None):
+def untis_import_mysql(terms: Optional[QuerySet] = None, version: Optional[int] = None):
     # School terms and validity ranges
-    validity_ref = import_terms(terms)
+    validity_ref = import_terms(terms, version=version)
 
     for validity_range in tqdm(
         validity_ref.values(), desc="Import data for terms", **TQDM_DEFAULTS
diff --git a/docs/admin/10_features.rst b/docs/admin/10_features.rst
index 0674261d8b81c6924f32458acfc17f91bf6807ec..8d6e0c2a73d58c43ff5960cc3674b2ef12149650 100644
--- a/docs/admin/10_features.rst
+++ b/docs/admin/10_features.rst
@@ -14,7 +14,7 @@ Supported Untis features
 ------------------------
 
 Not all features of Untis are supported in AlekSIS. The following
-information form Untis can be imported into AlekSIS:
+information from Untis can be imported into AlekSIS:
 
 * Terms
 * Holidays
@@ -26,6 +26,9 @@ information form Untis can be imported into AlekSIS:
 * Substitutions, extra lessons, cancellations
 * Events
 
+The Untis integration supports the versioning features of Untis. By default,
+the most recent version of each object is imported.
+
 Currently, the following features are known not to be supported:
 
 * Students, student groups, student choices
diff --git a/docs/admin/20_configuration.rst b/docs/admin/20_configuration.rst
index 7703e31eee1c1b922b3bc2585a2be051482cb59d..9984da36cbdd7c181b4263f00c51f8d1da779a39 100644
--- a/docs/admin/20_configuration.rst
+++ b/docs/admin/20_configuration.rst
@@ -92,7 +92,9 @@ is also already imported when it becomes reelvant.
 
 In general, all tasks will do nothing if there is no matching Untis term.
 
-To use these tasks, you have to add them as periodic tasks.
+To use these tasks, you have to add them as periodic tasks. By default, they will
+import the most recent plan version from Untis. To select a specific version (i.e.
+to import an older snapshot), you can pass the ``version`` argument in the tasks.
 
 How existing data is matched
 ----------------------------