diff --git a/program/models.py b/program/models.py
index 0b634d0c51b848ebe319dd0113d4de35909c66a8..f11245b284d1a878abd38bb890dfbb08241cc019 100644
--- a/program/models.py
+++ b/program/models.py
@@ -323,25 +323,25 @@ class Schedule(models.Model):
             True if sdl.get("add_business_days_only") is True else False
         )
 
-        # TODO: replace `dstart` with `first_date` when the dashboard is updated
-        first_date = parse_date(str(sdl["dstart"]))
-        # TODO: replace `tstart` with `start_time` when the dashboard is updated
+        first_date = parse_date(str(sdl["first_date"]))
         start_time = (
-            sdl["tstart"] + ":00" if len(str(sdl["tstart"])) == 5 else sdl["tstart"]
+            sdl["start_time"] + ":00"
+            if len(str(sdl["start_time"])) == 5
+            else sdl["start_time"]
+        )
+        end_time = (
+            sdl["end_time"] + ":00"
+            if len(str(sdl["end_time"])) == 5
+            else sdl["end_time"]
         )
-        # TODO: replace `tend` with `end_time` when the dashboard is updated
-        end_time = sdl["tend"] + ":00" if len(str(sdl["tend"])) == 5 else sdl["tend"]
 
         start_time = parse_time(str(start_time))
         end_time = parse_time(str(end_time))
 
-        # TODO: replace `until` with `last_date` when the dashboard is updated
-        if sdl["until"]:
-            last_date = parse_date(str(sdl["until"]))
+        if sdl["last_date"]:
+            last_date = parse_date(str(sdl["last_date"]))
         else:
-            # If no until date was set
-            # Set it to the end of the year
-            # Or add x days
+            # If last_date was not set, set it to the end of the year or add x days
             if AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR:
                 year = timezone.now().year
                 last_date = parse_date(f"{year}-12-31")
@@ -350,10 +350,9 @@ class Schedule(models.Model):
                     days=+AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE
                 )
 
-        # TODO: replace `byweekday` with `by_weekday` when the dashboard is updated
         schedule = Schedule(
             pk=pk,
-            by_weekday=sdl["byweekday"],
+            by_weekday=sdl["by_weekday"],
             rrule=rrule,
             first_date=first_date,
             start_time=start_time,
@@ -373,7 +372,7 @@ class Schedule(models.Model):
     def generate_timeslots(schedule):
         """
         Returns a list of timeslot objects based on a schedule and its rrule
-        Returns past timeslots as well, starting from dstart (not today)
+        Returns past timeslots as well, starting from first_date (not today)
         """
 
         by_week_no = None
@@ -696,7 +695,7 @@ class Schedule(models.Model):
         # Generate schedule to be saved
         schedule = Schedule.instantiate_upcoming(sdl, show_pk, schedule_pk)
 
-        # Copy if dstart changes for generating timeslots
+        # Copy if first_date changes for generating timeslots
         gen_schedule = schedule
 
         # Generate timeslots
@@ -742,13 +741,13 @@ class Schedule(models.Model):
 
         if schedule.rrule.freq > 0 and schedule.first_date == schedule.last_date:
             raise ValidationError(
-                _("Start and until dates mustn't be the same"),
+                _("Start and end dates must not be the same."),
                 code="no-same-day-start-and-end",
             )
 
         if schedule.last_date < schedule.first_date:
             raise ValidationError(
-                _("Until date mustn't be before start"),
+                _("End date mustn't be before start."),
                 code="no-start-after-end",
             )
 
diff --git a/program/serializers.py b/program/serializers.py
index ee5488be3cac05a12c20d6893e753555247b2a37..3ef7853fe0607197e3d206588af14f90e83b9436 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -36,7 +36,6 @@ from program.models import (
     MusicFocus,
     Note,
     NoteLink,
-    RRule,
     Schedule,
     Show,
     TimeSlot,
@@ -405,35 +404,16 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
 
 
 class ScheduleSerializer(serializers.ModelSerializer):
-    rrule = serializers.PrimaryKeyRelatedField(
-        queryset=RRule.objects.all(),
-        help_text=Schedule.rrule.field.help_text,
-    )
-    show = serializers.PrimaryKeyRelatedField(
-        queryset=Show.objects.all(),
-        help_text=Schedule.show.field.help_text,
-    )
-    # TODO: remove this when the dashboard is updated
-    byweekday = serializers.IntegerField(
-        source="by_weekday",
-        help_text=Schedule.by_weekday.field.help_text,
-    )
-    dstart = serializers.DateField(
-        source="first_date",
-        help_text=Schedule.first_date.field.help_text,
-    )
-    tstart = serializers.TimeField(
-        source="start_time",
-        help_text=Schedule.start_time.field.help_text,
-    )
-    tend = serializers.TimeField(
-        source="end_time",
-        help_text=Schedule.end_time.field.help_text,
-    )
-    until = serializers.DateField(
-        source="last_date",
-        help_text=Schedule.last_date.field.help_text,
-    )
+    class Meta:
+        model = Schedule
+        fields = "__all__"
+
+
+class UnsavedScheduleSerializer(ScheduleSerializer):
+    id = serializers.IntegerField(allow_null=True)
+
+
+class ScheduleInRequestSerializer(ScheduleSerializer):
     dryrun = serializers.BooleanField(
         write_only=True,
         required=False,
@@ -464,11 +444,11 @@ class ScheduleSerializer(serializers.ModelSerializer):
     def update(self, instance, validated_data):
         """Update and return an existing Schedule instance, given the validated data."""
 
-        instance.by_weekday = validated_data.get("byweekday", instance.by_weekday)
-        instance.first_date = validated_data.get("dstart", instance.first_date)
-        instance.start_time = validated_data.get("tstart", instance.start_time)
-        instance.end_time = validated_data.get("tend", instance.end_time)
-        instance.last_date = validated_data.get("until", instance.last_date)
+        instance.by_weekday = validated_data.get("by_weekday", instance.by_weekday)
+        instance.first_date = validated_data.get("first_date", instance.first_date)
+        instance.start_time = validated_data.get("start_time", instance.start_time)
+        instance.end_time = validated_data.get("end_time", instance.end_time)
+        instance.last_date = validated_data.get("last_date", instance.last_date)
         instance.is_repetition = validated_data.get(
             "is_repetition", instance.is_repetition
         )
@@ -525,41 +505,24 @@ class DryRunTimeSlotSerializer(serializers.Serializer):
 
 
 class ScheduleCreateUpdateRequestSerializer(serializers.Serializer):
-    schedule = ScheduleSerializer()
-    solutions = serializers.DictField(child=serializers.ChoiceField(SOLUTION_CHOICES))
+    schedule = ScheduleInRequestSerializer()
+    solutions = serializers.DictField(
+        child=serializers.ChoiceField(SOLUTION_CHOICES), required=False
+    )
     notes = serializers.DictField(child=serializers.IntegerField(), required=False)
     playlists = serializers.DictField(child=serializers.IntegerField(), required=False)
 
 
-# TODO: There shouldn’t be a separate ScheduleSerializer for use in responses.
-#       Instead the default serializer should be used. Unfortunately, the
-#       code that generates the data creates custom dicts with this particular format.
-class ScheduleInResponseSerializer(serializers.Serializer):
-    # "Schedule schema type" is the rendered name of the ScheduleSerializer.
-    """
-    For documentation on the individual fields see the
-    Schedule schema type.
-    """
-    add_business_days_only = serializers.BooleanField()
-    add_days_no = serializers.IntegerField(allow_null=True)
-    by_weekday = serializers.IntegerField()
-    default_playlist_id = serializers.IntegerField(allow_null=True)
-    end_time = serializers.TimeField()
-    first_date = serializers.DateField()
-    id = serializers.PrimaryKeyRelatedField(queryset=Schedule.objects.all())
-    is_repetition = serializers.BooleanField()
-    last_date = serializers.DateField()
-    rrule = serializers.PrimaryKeyRelatedField(queryset=RRule.objects.all())
-    show = serializers.PrimaryKeyRelatedField(queryset=Note.objects.all())
-    start_time = serializers.TimeField()
-
-
-class ScheduleConflictResponseSerializer(serializers.Serializer):
+class ScheduleResponseSerializer(serializers.Serializer):
     projected = ProjectedTimeSlotSerializer(many=True)
     solutions = serializers.DictField(child=serializers.ChoiceField(SOLUTION_CHOICES))
     notes = serializers.DictField(child=serializers.IntegerField())
     playlists = serializers.DictField(child=serializers.IntegerField())
-    schedule = ScheduleInResponseSerializer()
+    schedule = ScheduleSerializer()
+
+
+class ScheduleConflictResponseSerializer(ScheduleResponseSerializer):
+    schedule = UnsavedScheduleSerializer()
 
 
 class ScheduleDryRunResponseSerializer(serializers.Serializer):
diff --git a/program/views.py b/program/views.py
index e0f7b4d893f9c8d1ec21198f1b0b2f60441df75a..8d18a2db210c52fb59f1199458faf268c2e3d351 100644
--- a/program/views.py
+++ b/program/views.py
@@ -58,6 +58,7 @@ from program.serializers import (
     ScheduleConflictResponseSerializer,
     ScheduleCreateUpdateRequestSerializer,
     ScheduleDryRunResponseSerializer,
+    ScheduleResponseSerializer,
     ScheduleSerializer,
     ShowSerializer,
     TimeSlotSerializer,
@@ -344,9 +345,10 @@ class APIShowViewSet(DisabledObjectPermissionCheckMixin, viewsets.ModelViewSet):
 @extend_schema_view(
     create=extend_schema(
         summary="Create a new schedule.",
+        request=ScheduleCreateUpdateRequestSerializer,
         responses={
             status.HTTP_201_CREATED: OpenApiResponse(
-                response=ScheduleConflictResponseSerializer,
+                response=ScheduleResponseSerializer,
                 description=(
                     "Signals the successful creation of the schedule and of the projected "
                     "timeslots."
@@ -366,9 +368,9 @@ class APIShowViewSet(DisabledObjectPermissionCheckMixin, viewsets.ModelViewSet):
                     Returned in case the request contained invalid data.
 
                     This may happen if:
-                    * the until date is before the start date (`no-start-after-end`),
+                    * the last date is before the start date (`no-start-after-end`),
                       in which case you should correct either the start or until date.
-                    * The start and until date are the same (`no-same-day-start-and-end`).
+                    * The start and last date are the same (`no-same-day-start-and-end`).
                       This is only allowed for single timeslots with the recurrence rule
                       set to `once`. You should fix either the start or until date.
                     * The number of conflicts and solutions aren’t the same
@@ -410,8 +412,14 @@ class APIShowViewSet(DisabledObjectPermissionCheckMixin, viewsets.ModelViewSet):
         },
     ),
     retrieve=extend_schema(summary="Retrieve a single schedule."),
-    update=extend_schema(summary="Update an existing schedule."),
-    partial_update=extend_schema(summary="Partially update an existing schedule."),
+    update=extend_schema(
+        summary="Update an existing schedule.",
+        request=ScheduleCreateUpdateRequestSerializer,
+    ),
+    partial_update=extend_schema(
+        summary="Partially update an existing schedule.",
+        request=ScheduleCreateUpdateRequestSerializer,
+    ),
     destroy=extend_schema(summary="Delete an existing schedule."),
     list=extend_schema(summary="List all schedules."),
 )