diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0007_systemevent.py b/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0007_systemevent.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c9244dae2cdb26ba25dada3ed13c93facafe68e
--- /dev/null
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0007_systemevent.py
@@ -0,0 +1,127 @@
+# Generated by Django 3.0.9 on 2021-10-18 14:36
+
+from django.conf import settings
+import django.contrib.postgres.fields
+import django.contrib.postgres.fields.jsonb
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('tmssapp', '0006_subtask_obsolete_since'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='SystemEvent',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, default=list, help_text='User-defined search keywords for object.', size=8)),
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')),
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')),
+                ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)),
+                ('description', models.CharField(blank=True, default='', help_text='A longer description of this object.', max_length=255)),
+                ('start', models.DateTimeField(help_text='When this event started.')),
+                ('stop', models.DateTimeField(help_text='When this event stopped (NULLable).', null=True)),
+                ('notes', models.CharField(help_text='Any additional information', max_length=255, null=True)),
+                ('affected_hardware_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Properties of this event, e.g. station list and other hardware affected')),
+                ('jira_url', models.CharField(help_text='Link to JIRA issue (if any)', max_length=255, null=True)),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+        migrations.CreateModel(
+            name='SystemEventSeverity',
+            fields=[
+                ('value', models.CharField(max_length=128, primary_key=True, serialize=False, unique=True)),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+        migrations.CreateModel(
+            name='SystemEventStatus',
+            fields=[
+                ('value', models.CharField(max_length=128, primary_key=True, serialize=False, unique=True)),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+        migrations.CreateModel(
+            name='SystemEventSubtype',
+            fields=[
+                ('value', models.CharField(max_length=128, primary_key=True, serialize=False, unique=True)),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+        migrations.CreateModel(
+            name='SystemEventTemplate',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, default=list, help_text='User-defined search keywords for object.', size=8)),
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Moment of object creation.')),
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Moment of last object update.')),
+                ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)),
+                ('description', models.CharField(blank=True, default='', help_text='A longer description of this object.', max_length=255)),
+                ('version', models.IntegerField(editable=False, help_text='Version of this template (with respect to other templates of the same name)')),
+                ('schema', django.contrib.postgres.fields.jsonb.JSONField(help_text='Schema for the configurable parameters needed to use this template.')),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+        migrations.CreateModel(
+            name='SystemEventType',
+            fields=[
+                ('value', models.CharField(max_length=128, primary_key=True, serialize=False, unique=True)),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+        migrations.AddConstraint(
+            model_name='systemeventtemplate',
+            constraint=models.UniqueConstraint(fields=('name', 'version'), name='systemeventtemplate_unique_name_version'),
+        ),
+        migrations.AddField(
+            model_name='systemevent',
+            name='affected_hardware_template',
+            field=models.ForeignKey(help_text='Template for the affected_hardware_doc.', on_delete=django.db.models.deletion.PROTECT, to='tmssapp.SystemEventTemplate'),
+        ),
+        migrations.AddField(
+            model_name='systemevent',
+            name='affected_tasks',
+            field=models.ManyToManyField(blank=True, help_text='The task blueprints that are affected by this issue', related_name='system_events', to='tmssapp.TaskBlueprint'),
+        ),
+        migrations.AddField(
+            model_name='systemevent',
+            name='created_by',
+            field=models.ForeignKey(help_text='User who created this entry.', on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
+        ),
+        migrations.AddField(
+            model_name='systemevent',
+            name='issue_subtype',
+            field=models.ForeignKey(help_text='The subtype that classifies this issue', on_delete=django.db.models.deletion.PROTECT, to='tmssapp.SystemEventSubtype'),
+        ),
+        migrations.AddField(
+            model_name='systemevent',
+            name='issue_type',
+            field=models.ForeignKey(help_text='The main type that classifies this issue', on_delete=django.db.models.deletion.PROTECT, to='tmssapp.SystemEventType'),
+        ),
+        migrations.AddField(
+            model_name='systemevent',
+            name='severity',
+            field=models.ForeignKey(help_text='The subtype that classifies this issue', on_delete=django.db.models.deletion.PROTECT, to='tmssapp.SystemEventSeverity'),
+        ),
+        migrations.AddField(
+            model_name='systemevent',
+            name='status',
+            field=models.ForeignKey(help_text='The current status of this issue', on_delete=django.db.models.deletion.PROTECT, to='tmssapp.SystemEventStatus'),
+        ),
+    ]
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0008_populate_systemevent.py b/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0008_populate_systemevent.py
new file mode 100644
index 0000000000000000000000000000000000000000..276e0dada2da5f7f6aac8254fd429caf563c5f60
--- /dev/null
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0008_populate_systemevent.py
@@ -0,0 +1,14 @@
+
+
+from django.db import migrations
+
+from lofar.sas.tmss.tmss.tmssapp.populate import *
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('tmssapp', '0007_systemevent'),
+    ]
+
+    operations = [migrations.RunPython(populate_system_event_choices)]
+
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
index f5d7828b5d11ad14b4657746b4d458bb7a489bf6..54699653af62a4361cd9fc90020bf7166ef01851 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
@@ -25,6 +25,7 @@ from lofar.sas.tmss.tmss.exceptions import BlueprintCreationException, TMSSExcep
 from django.db.models import Count
 from copy import deepcopy
 from lofar.common.util import subdict_of_pointer_items
+from .permissions import TMSSUser as User
 
 #
 # I/O
@@ -164,6 +165,52 @@ class ProjectState(AbstractChoice):
         SUSPENDED = "suspended"
 
 
+class SystemEventType(AbstractChoice):
+    """Defines the model and predefined list of possible issue_types of a SystemEvent.
+    The items in the Choices class below are automagically populated into the database via a data migration."""
+    class Choices(Enum):
+        CEP = "cep"
+        COBALT = "cobalt"
+        ENVIRONMENT = "environment"
+        HUMAN ="human"
+        NETWORK = "network"
+        STATION = "station"
+        SYSTEM = "system"
+        OTHER = "other"
+
+
+class SystemEventSubtype(AbstractChoice):
+    """Defines the model and predefined list of possible issue_subtypes of a SystemEvent.
+    The items in the Choices class below are automagically populated into the database via a data migration."""
+    class Choices(Enum):
+        CRASH = "crash"
+        DATALOSS = "dataloss"
+        HARDWARE = "hardware"
+        NOISY = "noisy"
+        OSCILLATING = "oscillating"
+        RFI = "rfi"
+        SETUP = "setup"
+        TEMPERATURE = "temperature"
+        OTHER = "other"
+
+
+class SystemEventSeverity(AbstractChoice):
+    """Defines the model and predefined list of possible severity levels of a SystemEvent.
+    The items in the Choices class below are automagically populated into the database via a data migration."""
+    class Choices(Enum):
+        FAILURE = "failure"
+        MINOR = "minor"
+        MAJOR = "major"
+
+
+class SystemEventStatus(AbstractChoice):
+    """Defines the model and predefined list of possible statuses of a SystemEvent.
+    The items in the Choices class below are automagically populated into the database via a data migration."""
+    class Choices(Enum):
+        OPEN = "open"
+        ANALYSED = "analysed"
+
+
 # concrete models
 
 class Setting(BasicCommon):
@@ -368,6 +415,9 @@ class ReservationStrategyTemplate(BaseStrategyTemplate):
 class ReservationTemplate(Template):
     pass
 
+class SystemEventTemplate(Template):
+    pass
+
 
 #
 # Instance Objects
@@ -1016,6 +1066,13 @@ class SchedulingUnitBlueprint(ProjectPropertyMixin, TemplateSchemaMixin, NamedCo
 
         return fields_found
 
+    @property
+    def system_events(self):
+        events = []
+        for task in self.task_blueprints.all():
+            events += task.system_events
+        return set(events)
+
 
 class TaskDraft(NamedCommon, TemplateSchemaMixin, ProjectPropertyMixin):
     short_description = CharField(max_length=32, help_text='A short description of this task, usually the name of the target and abbreviated task type.', blank=True, default="")
@@ -1438,3 +1495,17 @@ class Reservation(NamedCommon, TemplateSchemaMixin):
         self.annotate_validate_add_defaults_to_doc_using_template('specifications_doc', 'specifications_template')
         super().save(force_insert, force_update, using, update_fields)
 
+
+class SystemEvent(NamedCommon):
+    created_by = ForeignKey(User, null=False, on_delete=PROTECT, help_text='User who created this entry.')
+    start = DateTimeField(help_text='When this event started.')
+    stop = DateTimeField(null=True, help_text='When this event stopped (NULLable).')
+    issue_type = ForeignKey('SystemEventType', on_delete=PROTECT, help_text='The main type that classifies this issue')
+    issue_subtype = ForeignKey('SystemEventSubtype', on_delete=PROTECT, help_text='The subtype that classifies this issue')
+    severity = ForeignKey('SystemEventSeverity', on_delete=PROTECT, help_text='The subtype that classifies this issue')
+    notes = CharField(max_length=255, null=True, help_text='Any additional information')
+    status = ForeignKey('SystemEventStatus', on_delete=PROTECT, help_text='The current status of this issue')
+    affected_hardware_doc = JSONField(help_text='Properties of this event, e.g. station list and other hardware affected')
+    affected_hardware_template = ForeignKey('SystemEventTemplate', on_delete=PROTECT, help_text='Template for the affected_hardware_doc.')
+    affected_tasks = ManyToManyField('TaskBlueprint', blank=True, related_name='system_events', help_text='The task blueprints that are affected by this issue')
+    jira_url = CharField(max_length=255, null=True, help_text='Link to JIRA issue (if any)')
\ No newline at end of file
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/populate.py b/SAS/TMSS/backend/src/tmss/tmssapp/populate.py
index e7c757539af412c484ff799f7bb48ad9fe8b4056..629626766cc90f5e21e9398633b7bcc4b47ebf2c 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/populate.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/populate.py
@@ -134,6 +134,19 @@ def populate_choices(apps, schema_editor):
         executor.map(lambda choice_class: choice_class.objects.bulk_create([choice_class(value=x.value) for x in choice_class.Choices]),
                      choice_classes)
 
+def populate_system_event_choices(apps, schema_editor):
+    '''
+    populate each 'choice' table in the database with the 'static' list of 'choice'.Choices for
+    each SystemEvent-related 'choice'type that has been added in a later migration than the initial populate.
+    :return: None
+    '''
+    choice_classes = [SystemEventType, SystemEventSubtype, SystemEventSeverity, SystemEventStatus]
+
+    # upload choices in parallel
+    with ThreadPoolExecutor() as executor:
+        executor.map(lambda choice_class: choice_class.objects.bulk_create([choice_class(value=x.value) for x in choice_class.Choices]),
+                     choice_classes)
+
 def populate_subtask_allowed_state_transitions(apps, schema_editor):
     '''populate the SubtaskAllowedStateTransitions table with the allowed state transitions as defined by the design in https://support.astron.nl/confluence/display/TMSS/Subtask+State+Machine'''
     DEFINING = SubtaskState.objects.get(value=SubtaskState.Choices.DEFINING.value)
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/common_schema_template/affectedhardware-1.json b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/system_event_template/affectedhardware-1.json
similarity index 90%
rename from SAS/TMSS/backend/src/tmss/tmssapp/schemas/common_schema_template/affectedhardware-1.json
rename to SAS/TMSS/backend/src/tmss/tmssapp/schemas/system_event_template/affectedhardware-1.json
index c616feeecca18defca10051e11bc36c7406a31ad..8d89e603e422b37e8920d7beb0d92f3383632481 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/common_schema_template/affectedhardware-1.json
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/system_event_template/affectedhardware-1.json
@@ -1,5 +1,5 @@
 {
-  "$id": "http://127.0.0.1:8000/api/schemas/commonschematemplate/affectedhardware/1#",
+  "$id": "http://127.0.0.1:8000/api/schemas/systemeventtemplate/affectedhardware/1#",
   "$schema": "http://json-schema.org/draft-06/schema#",
   "description": "This schema defines the hardware that was affected by a system event.",
   "properties": {
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/serializers/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/serializers/specification.py
index d17bf85c214e9cf38e3167fd278e9ddc415d966e..4967b7fca4bdbbe5794f827f5d3d784ea16fd91d 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/serializers/specification.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/serializers/specification.py
@@ -404,3 +404,47 @@ class ProjectStateSerializer(DynamicRelationalHyperlinkedModelSerializer):
     class Meta:
         model = models.ProjectState
         fields = '__all__'
+
+
+class SystemEventTypeSerializer(DynamicRelationalHyperlinkedModelSerializer):
+
+    class Meta:
+        model = models.SystemEventType
+        fields = '__all__'
+
+
+class SystemEventSubtypeSerializer(DynamicRelationalHyperlinkedModelSerializer):
+
+    class Meta:
+        model = models.SystemEventSubtype
+        fields = '__all__'
+
+
+class SystemEventSeveritySerializer(DynamicRelationalHyperlinkedModelSerializer):
+
+    class Meta:
+        model = models.SystemEventSeverity
+        fields = '__all__'
+
+
+class SystemEventStatusSerializer(DynamicRelationalHyperlinkedModelSerializer):
+
+    class Meta:
+        model = models.SystemEventStatus
+        fields = '__all__'
+
+
+class SystemEventTemplateSerializer(AbstractTemplateSerializer):
+
+    class Meta:
+        model = models.SystemEventTemplate
+        fields = '__all__'
+
+
+class SystemEventSerializer(DynamicRelationalHyperlinkedModelSerializer):
+    affected_hardware_doc = JSONEditorField(schema_source='affected_hardware_template.schema')
+    created_by = UserSerializer(required=False)
+
+    class Meta:
+        model = models.SystemEvent
+        fields = '__all__'
\ No newline at end of file
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
index 75935d1ee3134c23085a5cf9baabaf2d342e773e..fe9046e3761e395f3226d1afae9da2936d485845 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
@@ -584,11 +584,36 @@ class ProjectCategoryViewSet(LOFARViewSet):
 
 class NumberInFilter(filters.BaseInFilter, filters.NumberFilter):
     """
-    Custom filter for comma-separated lists of numbers
+    Custom filter that accepts a comma-separated lists of numbers.
+    Returns objects where the (single) numeric value of the filtered field is in the provided list.
     """
     pass
 
 
+class CharInFilter(filters.BaseInFilter, filters.CharFilter):
+    """
+    Custom filter that accepts a comma-separated lists of numbers.
+    Filters for objects where the (single) numeric value of the filtered field is in the provided list.
+    """
+    pass
+
+
+class ListContainsAnyFilter(filters.BaseCSVFilter):
+    """
+    Custom filter for where both the filtered field and the filter input are comma-separated lists.
+    Filters for objects where any of the values in the provided list is contained in the filtered field.
+    """
+    def filter(self, qs, values):
+        from django.db.models import Q
+        query = Q()
+        if not values:
+            return qs
+        else:
+            for value in values:
+                query |= Q(**{self.field_name+'__contains': value.strip()})
+        return qs.filter(query)
+
+
 class FloatRangeField(filter_fields.RangeField):
     """
     Custom range field for float values. The normal django filter_fields.RangeField uses (integer) decimal fields.
@@ -1009,7 +1034,15 @@ class SchedulingUnitBlueprintViewSet(LOFARViewSet):
         return Response(serializers.SchedulingUnitDraftExtendedSerializer(scheduling_unit_draft_copy, context={'request':request}).data,
                         status=status.HTTP_201_CREATED)
 
-
+    @swagger_auto_schema(responses={200: 'The system events of this scheduling unit blueprint',
+                                    403: 'forbidden'},
+                         operation_description="Get the system events of this scheduling unit blueprint.")
+    @action(methods=['get'], detail=True, url_name="system_events")
+    def system_events(self, request, pk=None):
+        sub = get_object_or_404(models.SchedulingUnitBlueprint, pk=pk)
+        system_events = self.filter_queryset(sub.system_events)
+        serializer = self.get_serializer(system_events, many=True)
+        return RestResponse(serializer.data)
 
 
 class SchedulingUnitBlueprintExtendedViewSet(SchedulingUnitBlueprintViewSet):
@@ -1311,6 +1344,17 @@ class TaskBlueprintViewSet(LOFARViewSet):
         return RestResponse(serializer.data)
 
 
+    @swagger_auto_schema(responses={200: 'The system events of this task blueprint',
+                                    403: 'forbidden'},
+                         operation_description="Get the system events of this task blueprint.")
+    @action(methods=['get'], detail=True, url_name="system_events")
+    def system_events(self, request, pk=None):
+        tb = get_object_or_404(models.TaskBlueprint, pk=pk)
+        system_events = self.filter_queryset(tb.system_events)
+        serializer = self.get_serializer(system_events, many=True)
+        return RestResponse(serializer.data)
+
+
 class TaskBlueprintNestedViewSet(LOFARNestedViewSet):
     queryset = models.TaskBlueprint.objects.all()
     serializer_class = serializers.TaskBlueprintSerializer
@@ -1384,3 +1428,64 @@ class PriorityQueueTypeViewSet(LOFARViewSet):
 class ProjectStateViewSet(LOFARViewSet):
     queryset = models.ProjectState.objects.all()
     serializer_class = serializers.ProjectStateSerializer
+
+
+class SystemEventTypeViewSet(LOFARViewSet):
+    queryset = models.SystemEventType.objects.all()
+    serializer_class = serializers.SystemEventTypeSerializer
+
+
+class SystemEventSubtypeViewSet(LOFARViewSet):
+    queryset = models.SystemEventSubtype.objects.all()
+    serializer_class = serializers.SystemEventSubtypeSerializer
+
+
+class SystemEventSeverityViewSet(LOFARViewSet):
+    queryset = models.SystemEventSeverity.objects.all()
+    serializer_class = serializers.SystemEventSeveritySerializer
+
+
+class SystemEventStatusViewSet(LOFARViewSet):
+    queryset = models.SystemEventStatus.objects.all()
+    serializer_class = serializers.SystemEventStatusSerializer
+
+
+class SystemEventTemplateViewSet(AbstractTemplateViewSet):
+    queryset = models.SystemEventTemplate.objects.all()
+    serializer_class = serializers.SystemEventTemplateSerializer
+
+
+class SystemEventFilter(filters.FilterSet):
+    name = filters.CharFilter(field_name='name', lookup_expr='icontains')
+    created_by = filters.CharFilter(field_name='created_by__username', lookup_expr='icontains')
+    id = NumberInFilter(field_name='id', lookup_expr='in')
+    id_min = filters.NumberFilter(field_name='id', lookup_expr='gte')
+    id_max = filters.NumberFilter(field_name='id', lookup_expr='lte')
+    created_at = filters.IsoDateTimeFromToRangeFilter(field_name='created_at')
+    updated_at = filters.IsoDateTimeFromToRangeFilter(field_name='updated_at')
+    description = filters.CharFilter(field_name='description', lookup_expr='icontains')
+    start = filters.IsoDateTimeFromToRangeFilter(field_name='start')
+    stop = filters.IsoDateTimeFromToRangeFilter(field_name='stop')
+    issue_type = filters.ModelMultipleChoiceFilter(field_name='issue_type', queryset=models.SystemEventType.objects.all())
+    issue_subtype = filters.ModelMultipleChoiceFilter(field_name='issue_subtype', queryset=models.SystemEventSubtype.objects.all())
+    severity = filters.ModelMultipleChoiceFilter(field_name='severity', queryset=models.SystemEventSeverity.objects.all())
+    notes = filters.CharFilter(field_name='notes', lookup_expr='icontains')
+    status = filters.ModelMultipleChoiceFilter(field_name='status', queryset=models.SystemEventStatus.objects.all())
+    affected_hardware_doc_stations = ListContainsAnyFilter(field_name='affected_hardware_doc__stations')
+    affected_hardware_template_name = filters.CharFilter(field_name='affected_hardware_template__name', lookup_expr='icontains')
+    affected_tasks = filters.ModelMultipleChoiceFilter(field_name='affected_tasks', queryset=models.TaskBlueprint.objects.all())
+    jira_url = filters.CharFilter(field_name='jira_url', lookup_expr='icontains')
+
+    class Meta:
+        model = models.SystemEvent
+        fields = '__all__'
+        filter_overrides = FILTER_OVERRIDES
+
+
+class SystemEventViewSet(LOFARViewSet):
+    queryset = models.SystemEvent.objects.all()
+    serializer_class = serializers.SystemEventSerializer
+    filter_class = SystemEventFilter
+
+    def perform_create(self, serializer):
+        serializer.save(created_by=self.request.user)
diff --git a/SAS/TMSS/backend/src/tmss/urls.py b/SAS/TMSS/backend/src/tmss/urls.py
index fcd6f55b39c3ee0c26090ae2a5465b4610176f18..790db62e4ade2fcf3018ccd22d489144a6e89fca 100644
--- a/SAS/TMSS/backend/src/tmss/urls.py
+++ b/SAS/TMSS/backend/src/tmss/urls.py
@@ -133,6 +133,10 @@ router.register(r'quantity', viewsets.QuantityViewSet)
 router.register(r'task_type', viewsets.TaskTypeViewSet)
 router.register(r'priority_queue_type', viewsets.PriorityQueueTypeViewSet)
 router.register(r'project_state', viewsets.ProjectStateViewSet)
+router.register(r'system_event_status', viewsets.SystemEventStatusViewSet)
+router.register(r'system_event_type', viewsets.SystemEventTypeViewSet)
+router.register(r'system_event_subtype', viewsets.SystemEventSubtypeViewSet)
+router.register(r'system_event_severity', viewsets.SystemEventSeverityViewSet)
 
 # templates
 router.register(r'common_schema_template', viewsets.CommonSchemaTemplateViewSet)
@@ -146,6 +150,7 @@ router.register(r'task_relation_selection_template', viewsets.TaskRelationSelect
 router.register(r'reservation_template', viewsets.ReservationTemplateViewSet)
 router.register(r'task_connector_type', viewsets.TaskConnectorTypeViewSet)
 router.register(r'reservation_strategy_template', viewsets.ReservationStrategyTemplateViewSet)
+router.register(r'system_event_template', viewsets.SystemEventTemplateViewSet)
 
 # instances
 router.register(r'cycle', viewsets.CycleViewSet)
@@ -156,6 +161,7 @@ router.register(r'project_quota', viewsets.ProjectQuotaViewSet)
 router.register(r'project_quota_archive_location', viewsets.ProjectQuotaArchiveLocationViewSet)
 router.register(r'setting', viewsets.SettingViewSet)
 router.register(r'reservation', viewsets.ReservationViewSet)
+router.register(r'system_event', viewsets.SystemEventViewSet)
 
 router.register(r'scheduling_set', viewsets.SchedulingSetViewSet)
 router.register(r'scheduling_unit_draft_extended', viewsets.SchedulingUnitDraftExtendedViewSet)
diff --git a/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py b/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py
index ee4e0ceac36ff5acb8100c810e5d76dbfcb765f3..6ca9620e536d7e238c86961a9fe77464050eabc8 100755
--- a/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py
+++ b/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py
@@ -3472,6 +3472,51 @@ class SystemRolePermissionTestCase(unittest.TestCase):
         self.assertEqual(response.status_code, 403)
         self.assertEqual(count, len(models.Project.objects.all()))
 
+class SystemEventTestCase(unittest.TestCase):
+
+    def test_SystemEvent_list_apiformat(self):
+        r = requests.get(BASE_URL + '/system_event/?format=api', auth=AUTH)
+        self.assertEqual(r.status_code, 200)
+        self.assertTrue("System Event List" in r.content.decode('utf8'))
+
+    def test_SystemEvent_POST_and_GET(self):
+        se_test_data = test_data_creator.SystemEvent("se_%s" % uuid.uuid4())
+
+        # POST and GET a new item and assert correctness
+        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/system_event/', se_test_data, 201, se_test_data)
+        url = r_dict['url']
+        GET_OK_and_assert_equal_expected_response(self, url, se_test_data)
+
+
+    def test_SystemEvent_filters_for_stations(self):
+        template_url = GET_and_assert_equal_expected_code(self, BASE_URL + '/system_event_template/?name=affectedhardware', 200)['results'][0]['url']
+
+        se_test_data_1 = test_data_creator.SystemEvent("se_%s" % uuid.uuid4(), affected_hardware_template=template_url,
+                                                       affected_hardware_doc={'stations': ['DE601', 'DE602']})
+        se_test_data_2 = test_data_creator.SystemEvent("se_%s" % uuid.uuid4(), affected_hardware_template=template_url,
+                                                       affected_hardware_doc={'stations': ['DE601', 'DE603']})
+        se_test_data_3 = test_data_creator.SystemEvent("se_%s" % uuid.uuid4(), affected_hardware_template=template_url,
+                                                       affected_hardware_doc={'stations': ['DE604', 'DE609']})
+
+        POST_and_assert_expected_response(self, BASE_URL + '/system_event/', se_test_data_1, 201, se_test_data_1)
+        POST_and_assert_expected_response(self, BASE_URL + '/system_event/', se_test_data_2, 201, se_test_data_2)
+        POST_and_assert_expected_response(self, BASE_URL + '/system_event/', se_test_data_3, 201, se_test_data_3)
+
+        #  assert
+        response_1 = GET_and_assert_equal_expected_code(self, BASE_URL + '/system_event/?affected_hardware_doc_stations=%s' % 'DE601', 200)
+        response_2 = GET_and_assert_equal_expected_code(self, BASE_URL + '/system_event/?affected_hardware_doc_stations=%s' % 'DE603,DE604', 200)
+        response_3 = GET_and_assert_equal_expected_code(self, BASE_URL + '/system_event/?affected_hardware_doc_stations=%s' % 'CS999', 200)
+
+        self.assertEqual(response_1['count'], 2)
+        self.assertIn(se_test_data_1['name'], str(response_1))
+        self.assertIn(se_test_data_2['name'], str(response_1))
+        self.assertNotIn(se_test_data_3['name'], str(response_1))
+        self.assertEqual(response_2['count'], 2)
+        self.assertNotIn(se_test_data_1['name'], str(response_2))
+        self.assertIn(se_test_data_2['name'], str(response_2))
+        self.assertIn(se_test_data_3['name'], str(response_2))
+        self.assertEqual(response_3['count'], 0)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/SAS/TMSS/backend/test/tmss_test_data_rest.py b/SAS/TMSS/backend/test/tmss_test_data_rest.py
index 7cdbbe22373511c76859dbbfc3b8b36c0989e22f..71bf02695ce6f4256cc44ab2f4435fe76a743020 100644
--- a/SAS/TMSS/backend/test/tmss_test_data_rest.py
+++ b/SAS/TMSS/backend/test/tmss_test_data_rest.py
@@ -866,6 +866,44 @@ class TMSSRESTTestDataCreator():
                 'DELETE': DELETE or [],
                 'POST': POST or []}
 
+
+    def SystemEventTemplate(self, name="systemeventtemplate1", schema:dict=None) -> dict:
+        if schema is None:
+            schema = minimal_json_schema(properties={"foo": {"type": "string", "default": "bar"}})
+
+        return { "name": name,
+                 "description": 'My description',
+                 "schema": schema,
+                 "tags": ["TMSS", "TESTING"]}
+
+    @property
+    def cached_system_event_template_url(self):
+        try:
+            return self._system_event_template_url
+        except AttributeError:
+            self._system_event_template_url = self.post_data_and_get_url(self.SystemEventTemplate(), '/system_event_template/')
+            return self._system_event_template_url
+
+
+    def SystemEvent(self, name="My System Event", start=None, stop=None, issue_type="human", issue_subtype="dataloss",
+                    severity="major", status="open", affected_hardware_doc=None, affected_hardware_template=None):
+
+        if affected_hardware_doc is None:
+            affected_hardware_doc = {}
+
+        if affected_hardware_template is None:
+            affected_hardware_template = self.cached_system_event_template_url
+
+        return {"affected_hardware_doc": affected_hardware_doc,
+                "affected_hardware_template": affected_hardware_template,
+                "issue_subtype": self.django_api_url + '/system_event_subtype/%s' % issue_subtype,
+                "issue_type": self.django_api_url + '/system_event_type/%s' % issue_type,
+                "name": name,
+                "severity": self.django_api_url + '/system_event_severity/%s' % severity,
+                "start": start if start is not None else datetime.utcnow().isoformat(),
+                "stop": stop if stop is not None else datetime.utcnow().isoformat(),
+                "status": self.django_api_url + '/system_event_status/%s' % status}
+
     def wipe_cache(self):
         cached_url_attributes = [attr for attr in self.__dict__.keys() if attr.startswith('_') and attr.endswith('_url')]
         for attr in cached_url_attributes: