diff --git a/aleksis/apps/alsijil/forms.py b/aleksis/apps/alsijil/forms.py
index 3d7f554eb2750784c3217eeaff4c09baae330520..99954b5308595d789eb3dca3a1e8ecf3602b9f6f 100644
--- a/aleksis/apps/alsijil/forms.py
+++ b/aleksis/apps/alsijil/forms.py
@@ -11,7 +11,7 @@ from material import Layout, Row
 from aleksis.apps.chronos.managers import TimetableType
 from aleksis.core.models import Group, Person
 
-from .models import LessonDocumentation, PersonalNote, PersonalNoteFilter
+from .models import ExcuseType, LessonDocumentation, PersonalNote, PersonalNoteFilter
 
 
 class LessonDocumentationForm(forms.ModelForm):
@@ -116,3 +116,11 @@ class PersonalNoteFilterForm(forms.ModelForm):
     class Meta:
         model = PersonalNoteFilter
         fields = ["identifier", "description", "regex"]
+
+
+class ExcuseTypeForm(forms.ModelForm):
+    layout = Layout("short_name", "name")
+
+    class Meta:
+        model = ExcuseType
+        fields = ["short_name", "name"]
diff --git a/aleksis/apps/alsijil/menus.py b/aleksis/apps/alsijil/menus.py
index 2b84cb6f7f70b644a34f79f170dfc4cb6751f773..c5fea59e3790fba0407d55d760434ac2e3dd0d3d 100644
--- a/aleksis/apps/alsijil/menus.py
+++ b/aleksis/apps/alsijil/menus.py
@@ -36,6 +36,12 @@ MENUS = {
                     "icon": "filter_list",
                     "validators": ["menu_generator.validators.is_superuser"],
                 },
+                {
+                    "name": _("Excuse types"),
+                    "url": "excuse_types",
+                    "icon": "label",
+                    "validators": ["menu_generator.validators.is_superuser"],
+                },
             ],
         }
     ]
diff --git a/aleksis/apps/alsijil/tables.py b/aleksis/apps/alsijil/tables.py
index bad0dc9f3923421035d0701251012461df13fec8..3a6762c3744ead9d02e9917aa975b530b5e448f0 100644
--- a/aleksis/apps/alsijil/tables.py
+++ b/aleksis/apps/alsijil/tables.py
@@ -17,3 +17,23 @@ class PersonalNoteFilterTable(tables.Table):
         text=_("Edit"),
         attrs={"a": {"class": "btn-flat waves-effect waves-orange"}},
     )
+
+
+class ExcuseTypeTable(tables.Table):
+    class Meta:
+        attrs = {"class": "highlight"}
+
+    name = tables.LinkColumn("edit_excuse_type", args=[A("id")])
+    short_name = tables.Column()
+    edit = tables.LinkColumn(
+        "edit_excuse_type",
+        args=[A("id")],
+        text=_("Edit"),
+        attrs={"a": {"class": "btn-flat waves-effect waves-orange orange-text"}},
+    )
+    delete = tables.LinkColumn(
+        "delete_excuse_type",
+        args=[A("id")],
+        text=_("Delete"),
+        attrs={"a": {"class": "btn-flat waves-effect waves-red red-text"}},
+    )
diff --git a/aleksis/apps/alsijil/templates/alsijil/excuse_type/create.html b/aleksis/apps/alsijil/templates/alsijil/excuse_type/create.html
new file mode 100644
index 0000000000000000000000000000000000000000..6fc6faefb2543cecf32b02e7dcb7ea2a40f3d73b
--- /dev/null
+++ b/aleksis/apps/alsijil/templates/alsijil/excuse_type/create.html
@@ -0,0 +1,18 @@
+{# -*- engine:django -*- #}
+
+{% extends "core/base.html" %}
+{% load material_form i18n %}
+
+{% block browser_title %}{% blocktrans %}Create excuse type{% endblocktrans %}{% endblock %}
+{% block page_title %}{% blocktrans %}Create excuse type{% endblocktrans %}{% endblock %}
+
+{% block content %}
+  {% include "alsijil/excuse_type/warning.html" %}
+
+  <form method="post">
+    {% csrf_token %}
+    {% form form=form %}{% endform %}
+    {% include "core/partials/save_button.html" %}
+  </form>
+
+{% endblock %}
diff --git a/aleksis/apps/alsijil/templates/alsijil/excuse_type/edit.html b/aleksis/apps/alsijil/templates/alsijil/excuse_type/edit.html
new file mode 100644
index 0000000000000000000000000000000000000000..78396ed66264cc19abdac2085d1cc89ff931bb38
--- /dev/null
+++ b/aleksis/apps/alsijil/templates/alsijil/excuse_type/edit.html
@@ -0,0 +1,17 @@
+{# -*- engine:django -*- #}
+
+{% extends "core/base.html" %}
+{% load material_form i18n %}
+
+{% block browser_title %}{% blocktrans %}Edit excuse type{% endblocktrans %}{% endblock %}
+{% block page_title %}{% blocktrans %}Edit excuse type{% endblocktrans %}{% endblock %}
+
+{% block content %}
+
+  <form method="post">
+    {% csrf_token %}
+    {% form form=form %}{% endform %}
+    {% include "core/partials/save_button.html" %}
+  </form>
+
+{% endblock %}
diff --git a/aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html b/aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html
new file mode 100644
index 0000000000000000000000000000000000000000..2be1f28c96e70f35e63fe4f5cefb50c232e38e0a
--- /dev/null
+++ b/aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html
@@ -0,0 +1,20 @@
+{# -*- engine:django -*- #}
+
+{% extends "core/base.html" %}
+
+{% load i18n %}
+{% load render_table from django_tables2 %}
+
+{% block browser_title %}{% blocktrans %}Excuse types{% endblocktrans %}{% endblock %}
+{% block page_title %}{% blocktrans %}Excuse types{% endblocktrans %}{% endblock %}
+
+{% block content %}
+  {% include "alsijil/excuse_type/warning.html" %}
+
+  <a class="btn green waves-effect waves-light" href="{% url 'create_excuse_type' %}">
+    <i class="material-icons left">add</i>
+    {% trans "Create excuse type" %}
+  </a>
+
+  {% render_table table %}
+{% endblock %}
diff --git a/aleksis/apps/alsijil/templates/alsijil/excuse_type/warning.html b/aleksis/apps/alsijil/templates/alsijil/excuse_type/warning.html
new file mode 100644
index 0000000000000000000000000000000000000000..d90d2e8205b1c91c18e74e02654fde3daebc4971
--- /dev/null
+++ b/aleksis/apps/alsijil/templates/alsijil/excuse_type/warning.html
@@ -0,0 +1,10 @@
+{% load i18n %}
+<div class="alert warning">
+  <p>
+    <i class="material-icons left">warning</i>
+    {% blocktrans %}
+      This function should only be used to define alternatives to the default excuse which also will be counted extra.
+      Don't use this to create a default excuse or if you don't divide between different types of excuse.
+    {% endblocktrans %}
+  </p>
+</div>
diff --git a/aleksis/apps/alsijil/urls.py b/aleksis/apps/alsijil/urls.py
index 4406a06852ae2489eaf5b84c66a28098d91f0010..89ab0ffe5f47c8cfebb015a6f76e597af4dd11dd 100644
--- a/aleksis/apps/alsijil/urls.py
+++ b/aleksis/apps/alsijil/urls.py
@@ -41,4 +41,20 @@ urlpatterns = [
         views.delete_personal_note_filter,
         name="delete_personal_note_filter",
     ),
+    path("excuse_types/", views.ExcuseTypeListView.as_view(), name="excuse_types"),
+    path(
+        "excuse_types/create/",
+        views.ExcuseTypeCreateView.as_view(),
+        name="create_excuse_type",
+    ),
+    path(
+        "excuse_types/<int:pk>/edit/",
+        views.ExcuseTypeEditView.as_view(),
+        name="edit_excuse_type",
+    ),
+    path(
+        "excuse_types/<int:pk>/delete/",
+        views.ExcuseTypeDeleteView.as_view(),
+        name="delete_excuse_type",
+    ),
 ]
diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py
index 8fa58f62a8fa267c92caa35b0de30fa90ed0ff8b..25868ba0dff775804e21038a4e6547353cffc2c2 100644
--- a/aleksis/apps/alsijil/views.py
+++ b/aleksis/apps/alsijil/views.py
@@ -5,27 +5,31 @@ from django.core.exceptions import PermissionDenied
 from django.db.models import Count, Exists, F, OuterRef, Q, Subquery, Sum
 from django.http import Http404, HttpRequest, HttpResponse, HttpResponseNotFound
 from django.shortcuts import get_object_or_404, redirect, render
-from django.urls import reverse
+from django.urls import reverse, reverse_lazy
 from django.utils.translation import ugettext as _
 
 from calendarweek import CalendarWeek
-from django_tables2 import RequestConfig
+from django_tables2 import RequestConfig, SingleTableView
+from reversion.views import RevisionMixin
+from rules.contrib.views import PermissionRequiredMixin
 
 from aleksis.apps.chronos.managers import TimetableType
 from aleksis.apps.chronos.models import LessonPeriod
 from aleksis.apps.chronos.util.chronos_helpers import get_el_by_pk
+from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView
 from aleksis.core.models import Group, Person, SchoolTerm
 from aleksis.core.util import messages
 
 from .forms import (
+    ExcuseTypeForm,
     LessonDocumentationForm,
     PersonalNoteFilterForm,
     PersonalNoteFormSet,
     RegisterAbsenceForm,
     SelectForm,
 )
-from .models import LessonDocumentation, PersonalNoteFilter
-from .tables import PersonalNoteFilterTable
+from .models import ExcuseType, LessonDocumentation, PersonalNoteFilter
+from .tables import ExcuseTypeTable, PersonalNoteFilterTable
 
 
 def lesson(
@@ -413,3 +417,44 @@ def delete_personal_note_filter(request: HttpRequest, id_: int) -> HttpResponse:
 
     context["personal_note_filter"] = personal_note_filter
     return redirect("list_personal_note_filters")
+
+
+class ExcuseTypeListView(SingleTableView, PermissionRequiredMixin):
+    """Table of all excuse types."""
+
+    model = ExcuseType
+    table_class = ExcuseTypeTable
+    permission_required = "core.view_excusetype"
+    template_name = "alsijil/excuse_type/list.html"
+
+
+class ExcuseTypeCreateView(AdvancedCreateView, PermissionRequiredMixin):
+    """Create view for excuse types."""
+
+    model = ExcuseType
+    form_class = ExcuseTypeForm
+    permission_required = "core.create_excusetype"
+    template_name = "alsijil/excuse_type/create.html"
+    success_url = reverse_lazy("excuse_types")
+    success_message = _("The excuse type has been created.")
+
+
+class ExcuseTypeEditView(AdvancedEditView, PermissionRequiredMixin):
+    """Edit view for excuse types."""
+
+    model = ExcuseType
+    form_class = ExcuseTypeForm
+    permission_required = "core.edit_excusetype"
+    template_name = "alsijil/excuse_type/edit.html"
+    success_url = reverse_lazy("excuse_types")
+    success_message = _("The excuse type has been saved.")
+
+
+class ExcuseTypeDeleteView(AdvancedDeleteView, PermissionRequiredMixin, RevisionMixin):
+    """Delete view for excuse types"""
+
+    model = ExcuseType
+    permission_required = "core.delete_excusetype"
+    template_name = "core/pages/delete.html"
+    success_url = reverse_lazy("excuse_types")
+    success_message = _("The excuse type has been deleted.")