diff --git a/program/serializers.py b/program/serializers.py
index 40679801918d5ebb594dba3a614116c9c6a30e12..690b42a0e252cf06fa543367eae3fe71caff260e 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -385,28 +385,38 @@ class ShowLinkSerializer(serializers.ModelSerializer):
 
 
 class ShowSerializer(serializers.HyperlinkedModelSerializer):
-    category = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(), many=True)
-    funding_category = serializers.PrimaryKeyRelatedField(queryset=FundingCategory.objects.all())
-    hosts = serializers.PrimaryKeyRelatedField(queryset=Host.objects.all(), many=True)
-    image = serializers.PrimaryKeyRelatedField(
-        allow_null=True,
-        queryset=Image.objects.all(),
-        required=False,
+    category_ids = serializers.PrimaryKeyRelatedField(
+        many=True, queryset=Category.objects.all(), source="category"
+    )
+    funding_category_id = serializers.PrimaryKeyRelatedField(
+        queryset=FundingCategory.objects.all()
+    )
+    host_ids = serializers.PrimaryKeyRelatedField(
+        many=True, queryset=Host.objects.all(), source="hosts"
+    )
+    image_id = serializers.PrimaryKeyRelatedField(
+        allow_null=True, queryset=Image.objects.all(), required=False
+    )
+    language_ids = serializers.PrimaryKeyRelatedField(
+        many=True, queryset=Language.objects.all(), source="language"
     )
-    language = serializers.PrimaryKeyRelatedField(queryset=Language.objects.all(), many=True)
     links = HostLinkSerializer(many=True, required=False)
-    logo = serializers.PrimaryKeyRelatedField(
-        allow_null=True,
-        queryset=Image.objects.all(),
-        required=False,
+    logo_id = serializers.PrimaryKeyRelatedField(
+        allow_null=True, queryset=Image.objects.all(), required=False
+    )
+    music_focus_ids = serializers.PrimaryKeyRelatedField(
+        many=True, queryset=MusicFocus.objects.all(), source="music_focus"
     )
-    music_focus = serializers.PrimaryKeyRelatedField(queryset=MusicFocus.objects.all(), many=True)
-    owners = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), many=True)
-    predecessor = serializers.PrimaryKeyRelatedField(
-        queryset=Show.objects.all(), required=False, allow_null=True
+    owner_ids = serializers.PrimaryKeyRelatedField(
+        many=True, queryset=User.objects.all(), source="owners"
     )
-    topic = serializers.PrimaryKeyRelatedField(queryset=Topic.objects.all(), many=True)
-    type = serializers.PrimaryKeyRelatedField(queryset=Type.objects.all())
+    predecessor_id = serializers.PrimaryKeyRelatedField(
+        allow_null=True, queryset=Show.objects.all(), required=False
+    )
+    topic_ids = serializers.PrimaryKeyRelatedField(
+        many=True, queryset=Topic.objects.all(), source="topic"
+    )
+    type_id = serializers.PrimaryKeyRelatedField(queryset=Type.objects.all())
 
     class Meta:
         model = Show
@@ -417,29 +427,29 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
             "updated_by",
         )
         fields = (
-            "category",
+            "category_ids",
             "cba_series_id",
             "default_playlist_id",
             "description",
             "email",
-            "funding_category",
-            "hosts",
+            "funding_category_id",
+            "host_ids",
             "id",
-            "image",
+            "image_id",
             "internal_note",
             "is_active",
             "is_public",
-            "language",
+            "language_ids",
             "links",
-            "logo",
-            "music_focus",
+            "logo_id",
+            "music_focus_ids",
             "name",
-            "owners",
-            "predecessor",
+            "owner_ids",
+            "predecessor_id",
             "short_description",
             "slug",
-            "topic",
-            "type",
+            "topic_ids",
+            "type_id",
         ) + read_only_fields
 
     def create(self, validated_data):
@@ -455,8 +465,18 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
         music_focus = validated_data.pop("music_focus")
         links_data = validated_data.pop("links", [])
 
+        # required
+        validated_data["funding_category"] = validated_data.pop("funding_category_id")
+        validated_data["type"] = validated_data.pop("type_id")
+
+        # optional
+        validated_data["image"] = validated_data.pop("image_id", None)
+        validated_data["logo"] = validated_data.pop("logo_id", None)
+        validated_data["predecessor"] = validated_data.pop("predecessor_id", None)
+
         show = Show.objects.create(
-            created_by=self.context.get("request").user.username, **validated_data
+            created_by=self.context.get("request").user.username,
+            **validated_data,
         )
 
         # Save many-to-many relationships
@@ -486,20 +506,20 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
         instance.description = validated_data.get("description", instance.description)
         instance.email = validated_data.get("email", instance.email)
         instance.funding_category = validated_data.get(
-            "funding_category", instance.funding_category
+            "funding_category_id", instance.funding_category
         )
-        instance.image = validated_data.get("image", instance.image)
+        instance.image = validated_data.get("image_id", instance.image)
         instance.internal_note = validated_data.get("internal_note", instance.internal_note)
         instance.is_active = validated_data.get("is_active", instance.is_active)
         instance.is_public = validated_data.get("is_public", instance.is_public)
-        instance.logo = validated_data.get("logo", instance.logo)
+        instance.logo = validated_data.get("logo_id", instance.logo)
         instance.name = validated_data.get("name", instance.name)
-        instance.predecessor = validated_data.get("predecessor", instance.predecessor)
+        instance.predecessor = validated_data.get("predecessor_id", instance.predecessor)
         instance.short_description = validated_data.get(
             "short_description", instance.short_description
         )
         instance.slug = validated_data.get("slug", instance.slug)
-        instance.type = validated_data.get("type", instance.type)
+        instance.type = validated_data.get("type_id", instance.type)
 
         instance.category.set(validated_data.get("category", instance.category))
         instance.hosts.set(validated_data.get("hosts", instance.hosts))
@@ -544,8 +564,8 @@ class ScheduleSerializer(serializers.ModelSerializer):
             "id",
             "is_repetition",
             "last_date",
-            "rrule",
-            "show",
+            "rrule_id",
+            "show_id",
             "start_time",
         )
 
@@ -577,20 +597,18 @@ class ScheduleInRequestSerializer(ScheduleSerializer):
             "first_date",
             "is_repetition",
             "last_date",
-            "rrule",
-            "show",
+            "rrule_id",
+            "show_id",
             "start_time",
         )
 
     def create(self, validated_data):
         """Create and return a new Schedule instance, given the validated data."""
 
-        rrule = validated_data.pop("rrule")
-        show = validated_data.pop("show")
+        validated_data["rrule"] = validated_data.pop("rrule_id")
+        validated_data["show"] = validated_data.pop("show_id")
 
         schedule = Schedule.objects.create(**validated_data)
-        schedule.rrule = rrule
-        schedule.show = show
 
         schedule.save()
         return schedule
@@ -607,8 +625,8 @@ class ScheduleInRequestSerializer(ScheduleSerializer):
         instance.default_playlist_id = validated_data.get(
             "default_playlist_id", instance.default_playlist_id
         )
-        instance.rrule = validated_data.get("rrule", instance.rrule)
-        instance.show = validated_data.get("show", instance.show)
+        instance.rrule = validated_data.get("rrule_id", instance.rrule)
+        instance.show = validated_data.get("show_id", instance.show)
         instance.add_days_no = validated_data.get("add_days_no", instance.add_days_no)
         instance.add_business_days_only = validated_data.get(
             "add_business_days_only", instance.add_business_days_only
@@ -623,10 +641,10 @@ class CollisionSerializer(serializers.Serializer):
     start = serializers.DateTimeField()
     end = serializers.DateTimeField()
     playlist_id = serializers.IntegerField(allow_null=True)
-    show = serializers.IntegerField()
+    show_id = serializers.IntegerField()
     show_name = serializers.CharField()
     repetition_of = serializers.IntegerField(allow_null=True)
-    schedule = serializers.IntegerField()
+    schedule_id = serializers.IntegerField()
     memo = serializers.CharField()
     note_id = serializers.IntegerField(allow_null=True)
 
@@ -642,11 +660,13 @@ class ProjectedTimeSlotSerializer(serializers.Serializer):
 
 class DryRunTimeSlotSerializer(serializers.Serializer):
     id = serializers.PrimaryKeyRelatedField(queryset=TimeSlot.objects.all(), allow_null=True)
-    schedule = serializers.PrimaryKeyRelatedField(queryset=Schedule.objects.all(), allow_null=True)
+    schedule_id = serializers.PrimaryKeyRelatedField(
+        queryset=Schedule.objects.all(), allow_null=True
+    )
     playlist_id = serializers.IntegerField(allow_null=True)
     start = serializers.DateField()
     end = serializers.DateField()
-    repetition_of = serializers.IntegerField(allow_null=True)
+    repetition_of_id = serializers.IntegerField(allow_null=True)
     memo = serializers.CharField()
 
 
@@ -678,9 +698,11 @@ class ScheduleDryRunResponseSerializer(serializers.Serializer):
 
 
 class TimeSlotSerializer(serializers.ModelSerializer):
-    show = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all(), required=False)
-    schedule = serializers.PrimaryKeyRelatedField(queryset=Schedule.objects.all(), required=False)
-    repetition_of = serializers.PrimaryKeyRelatedField(
+    show_id = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all(), required=False)
+    schedule_id = serializers.PrimaryKeyRelatedField(
+        queryset=Schedule.objects.all(), required=False
+    )
+    repetition_of_id = serializers.PrimaryKeyRelatedField(
         allow_null=True,
         queryset=TimeSlot.objects.all(),
         required=False,
@@ -691,14 +713,14 @@ class TimeSlotSerializer(serializers.ModelSerializer):
         read_only_fields = (
             "id",
             "end",
-            "schedule",
-            "show",
+            "schedule_id",
+            "show_id",
             "start",
         )
         fields = (
             "memo",
             "playlist_id",
-            "repetition_of",
+            "repetition_of_id",
         ) + read_only_fields
 
     def update(self, instance, validated_data):
@@ -706,7 +728,7 @@ class TimeSlotSerializer(serializers.ModelSerializer):
 
         # Only save certain fields
         instance.memo = validated_data.get("memo", instance.memo)
-        instance.repetition_of = validated_data.get("repetition_of", instance.repetition_of)
+        instance.repetition_of = validated_data.get("repetition_of", instance.repetition_of_id)
         instance.playlist_id = validated_data.get("playlist_id", instance.playlist_id)
         instance.save()
         return instance
@@ -720,11 +742,14 @@ class NoteLinkSerializer(serializers.ModelSerializer):
 
 class NoteSerializer(serializers.ModelSerializer):
     contributors = serializers.PrimaryKeyRelatedField(queryset=Host.objects.all(), many=True)
-    image = serializers.PrimaryKeyRelatedField(
+    image_id = serializers.PrimaryKeyRelatedField(
         queryset=Image.objects.all(), required=False, allow_null=True
     )
     links = NoteLinkSerializer(many=True, required=False)
-    timeslot = serializers.PrimaryKeyRelatedField(queryset=TimeSlot.objects.all(), required=False)
+    playlist_id = serializers.IntegerField(required=False)
+    timeslot_id = serializers.PrimaryKeyRelatedField(
+        queryset=TimeSlot.objects.all(), required=False
+    )
 
     class Meta:
         model = Note
@@ -740,14 +765,14 @@ class NoteSerializer(serializers.ModelSerializer):
             "content",
             "contributors",
             "id",
-            "image",
+            "image_id",
             "links",
-            "owner",
-            "playlist",
+            "owner_id",
+            "playlist_id",
             "slug",
             "summary",
             "tags",
-            "timeslot",
+            "timeslot_id",
             "title",
         ) + read_only_fields
 
@@ -757,6 +782,12 @@ class NoteSerializer(serializers.ModelSerializer):
         links_data = validated_data.pop("links", [])
         contributors = validated_data.pop("contributors", [])
 
+        # required
+        validated_data["timeslot"] = validated_data.pop("timeslot_id")
+
+        # optional
+        validated_data["image"] = validated_data.pop("image_id", None)
+
         # the creator of the note is the owner
         note = Note.objects.create(
             created_by=self.context.get("request").user.username,
@@ -791,10 +822,10 @@ class NoteSerializer(serializers.ModelSerializer):
 
         instance.cba_id = validated_data.get("cba_id", instance.cba_id)
         instance.content = validated_data.get("content", instance.content)
-        instance.image = validated_data.get("image", instance.image)
+        instance.image = validated_data.get("image", instance.image_id)
         instance.slug = validated_data.get("slug", instance.slug)
         instance.summary = validated_data.get("summary", instance.summary)
-        instance.timeslot = validated_data.get("timeslot", instance.timeslot)
+        instance.timeslot = validated_data.get("timeslot", instance.timeslot_id)
         instance.title = validated_data.get("title", instance.title)
 
         instance.contributors.set(validated_data.get("contributors", instance.contributors))
diff --git a/program/services.py b/program/services.py
index 480c4aef43b2d4d6a634169165aab59adcf8273d..005192dbc5e03ee064d710ef502c9b03c418ab94 100644
--- a/program/services.py
+++ b/program/services.py
@@ -47,19 +47,19 @@ class ScheduleData(TypedDict):
     id: int | None
     is_repetition: bool | None
     last_date: str | None
-    rrule: int
-    show: int | None
+    rrule_id: int
+    show_id: int | None
     start_time: str
 
 
 class Collision(TypedDict):
     end: str
-    id: int
+    timeslot_id: int
     memo: str
     note_id: int | None
     playlist_id: int | None
-    schedule: int
-    show: int
+    schedule_id: int
+    show_id: int
     show_name: str
     start: str
 
@@ -190,7 +190,7 @@ def resolve_conflicts(data: ScheduleCreateUpdateData, schedule_pk: int | None, s
             # Delete collision(s)
             for collision in timeslot["collisions"]:
                 try:
-                    to_delete.append(TimeSlot.objects.get(pk=collision["id"]))
+                    to_delete.append(TimeSlot.objects.get(pk=collision["timeslot_id"]))
                 except ObjectDoesNotExist:
                     pass
 
@@ -212,7 +212,7 @@ def resolve_conflicts(data: ScheduleCreateUpdateData, schedule_pk: int | None, s
                 ),
             )
 
-            existing_ts = TimeSlot.objects.get(pk=existing["id"])
+            existing_ts = TimeSlot.objects.get(pk=existing["timeslot_id"])
             existing_ts.start = parse_datetime(timeslot["end"])
             to_update.append(existing_ts)
 
@@ -232,7 +232,7 @@ def resolve_conflicts(data: ScheduleCreateUpdateData, schedule_pk: int | None, s
                 ),
             )
 
-            existing_ts = TimeSlot.objects.get(pk=existing["id"])
+            existing_ts = TimeSlot.objects.get(pk=existing["timeslot_id"])
             existing_ts.end = parse_datetime(timeslot["start"])
             to_update.append(existing_ts)
 
@@ -260,7 +260,7 @@ def resolve_conflicts(data: ScheduleCreateUpdateData, schedule_pk: int | None, s
                 ),
             )
 
-            existing_ts = TimeSlot.objects.get(pk=existing["id"])
+            existing_ts = TimeSlot.objects.get(pk=existing["timeslot_id"])
             existing_ts.end = parse_datetime(timeslot["start"])
             to_update.append(existing_ts)
 
@@ -366,7 +366,7 @@ def instantiate_upcoming_schedule(
     If the data does not contain a last_date, the Schedule instance will not contain a last_date.
     """
 
-    rrule = RRule.objects.get(pk=data["rrule"])
+    rrule = RRule.objects.get(pk=data["rrule_id"])
     show = Show.objects.get(pk=show_pk)
 
     is_repetition = data["is_repetition"] if "is_repetition" in data else False
@@ -635,13 +635,13 @@ def generate_conflicts(timeslots: list[TimeSlot]) -> Conflicts:
         for c in collision_list:
             # Add the collision
             collision = {
-                "id": c.id,
+                "timeslot_id": c.id,
                 "start": str(c.start),
                 "end": str(c.end),
                 "playlist_id": c.playlist_id,
-                "show": c.show.id,
+                "show_id": c.show.id,
                 "show_name": c.show.name,
-                "schedule": c.schedule_id,
+                "schedule_id": c.schedule_id,
                 "memo": c.memo,
             }