diff --git a/program/models.py b/program/models.py
index 6a58ae8dfd78afb6e82dbe409a37b0463ebf9132..06b4a775377cd16728627525303cc3e551a72260 100644
--- a/program/models.py
+++ b/program/models.py
@@ -35,9 +35,9 @@ class ScheduleConflictError(ValidationError):
 
 
 class Type(models.Model):
-    is_active = models.BooleanField(default=True)
-    name = models.CharField(max_length=32)
-    slug = models.SlugField(max_length=32, unique=True)
+    is_active = models.BooleanField(default=True, help_text="True if type is active.")
+    name = models.CharField(max_length=32, help_text="Name of the type.")
+    slug = models.SlugField(max_length=32, unique=True, help_text="Slug of the type.")
 
     class Meta:
         ordering = ("name",)
@@ -47,11 +47,11 @@ class Type(models.Model):
 
 
 class Category(models.Model):
-    description = models.TextField(blank=True)
-    is_active = models.BooleanField(default=True)
-    name = models.CharField(max_length=32)
-    slug = models.SlugField(max_length=32, unique=True)
-    subtitle = models.CharField(blank=True, max_length=32)
+    description = models.TextField(blank=True, help_text="Description of the category.")
+    is_active = models.BooleanField(default=True, help_text="True if category is active.")
+    name = models.CharField(max_length=32, help_text="Name of the category.")
+    slug = models.SlugField(max_length=32, unique=True, help_text="Slug of the category.")
+    subtitle = models.CharField(blank=True, max_length=32, help_text="Subtitle of the category.")
 
     class Meta:
         ordering = ("name",)
@@ -62,9 +62,9 @@ class Category(models.Model):
 
 
 class Topic(models.Model):
-    is_active = models.BooleanField(default=True)
-    name = models.CharField(max_length=32)
-    slug = models.SlugField(max_length=32, unique=True)
+    is_active = models.BooleanField(default=True, help_text="True if topic is active.")
+    name = models.CharField(max_length=32, help_text="Name of the topic.")
+    slug = models.SlugField(max_length=32, unique=True, help_text="Slug of the topic.")
 
     class Meta:
         ordering = ("name",)
@@ -74,9 +74,9 @@ class Topic(models.Model):
 
 
 class MusicFocus(models.Model):
-    is_active = models.BooleanField(default=True)
-    name = models.CharField(max_length=32)
-    slug = models.SlugField(max_length=32, unique=True)
+    is_active = models.BooleanField(default=True, help_text="True if music focus is active.")
+    name = models.CharField(max_length=32, help_text="Name of the music focus.")
+    slug = models.SlugField(max_length=32, unique=True, help_text="Slug of the music focus.")
 
     class Meta:
         ordering = ("name",)
@@ -87,9 +87,9 @@ class MusicFocus(models.Model):
 
 
 class FundingCategory(models.Model):
-    is_active = models.BooleanField(default=True)
-    name = models.CharField(max_length=32)
-    slug = models.SlugField(max_length=32, unique=True)
+    is_active = models.BooleanField(default=True, help_text="True if funding category is active.")
+    name = models.CharField(max_length=32, help_text="Name of the funding category.")
+    slug = models.SlugField(max_length=32, unique=True, help_text="Slug of the funding category.")
 
     class Meta:
         ordering = ("name",)
@@ -100,8 +100,8 @@ class FundingCategory(models.Model):
 
 
 class Language(models.Model):
-    is_active = models.BooleanField(default=True)
-    name = models.CharField(max_length=32)
+    is_active = models.BooleanField(default=True, help_text="True if language is active.")
+    name = models.CharField(max_length=32, help_text="Name of the language.")
 
     class Meta:
         ordering = ("name",)
@@ -113,9 +113,11 @@ class Language(models.Model):
 class License(models.Model):
     identifier = models.CharField(max_length=32, help_text="Identifier of the license")
     name = models.CharField(max_length=64, help_text="Name of the license")
-    needs_author = models.BooleanField(default=True)
-    requires_express_permission_for_publication = models.BooleanField(default=True)
-    url = models.URLField(default="", blank=True)
+    needs_author = models.BooleanField(default=True, help_text="True if license needs an author.")
+    requires_express_permission_for_publication = models.BooleanField(
+        default=True, help_text="True if express permission for publication required."
+    )
+    url = models.URLField(default="", blank=True, help_text="URL of the licence.")
 
     class Meta:
         ordering = ("name",)
@@ -125,9 +127,11 @@ class License(models.Model):
 
 
 class Image(models.Model):
-    alt_text = models.TextField(blank=True, default="")
-    credits = models.TextField(blank=True, default="")
-    is_use_explicitly_granted_by_author = models.BooleanField(default=False)
+    alt_text = models.TextField(blank=True, default="", help_text="Alternate text for the image.")
+    credits = models.TextField(blank=True, default="", help_text="Credits of the image")
+    is_use_explicitly_granted_by_author = models.BooleanField(
+        default=False, help_text="True if use is explicitly granted by author."
+    )
     height = models.PositiveIntegerField(blank=True, null=True)
     image = VersatileImageField(
         blank=True,
@@ -136,6 +140,7 @@ class Image(models.Model):
         ppoi_field="ppoi",
         upload_to="images",
         width_field="width",
+        help_text="The URI of the image.",
     )
     license = models.ForeignKey(
         License, null=True, on_delete=models.SET_NULL, related_name="images"
@@ -158,14 +163,16 @@ class Image(models.Model):
 
 
 class Host(models.Model):
-    biography = models.TextField(blank=True)
+    biography = models.TextField(blank=True, help_text="Biography of the host.")
     created_at = models.DateTimeField(auto_now_add=True)
     created_by = models.CharField(max_length=150)
-    email = models.EmailField(blank=True)
+    email = models.EmailField(blank=True, help_text="Email address of the host.")
     image = models.ForeignKey(Image, null=True, on_delete=models.CASCADE, related_name="hosts")
-    is_active = models.BooleanField(default=True)
-    name = models.CharField(max_length=128)
-    owners = models.ManyToManyField(User, blank=True, related_name="hosts")
+    is_active = models.BooleanField(default=True, help_text="True if host is active.")
+    name = models.CharField(max_length=128, help_text="Display name of the host.")
+    owners = models.ManyToManyField(
+        User, blank=True, related_name="hosts", help_text="User ID(s) identifying this host."
+    )
     updated_at = models.DateTimeField(auto_now=True, blank=True, null=True)
     updated_by = models.CharField(blank=True, default="", max_length=150)
 
@@ -183,7 +190,7 @@ class Host(models.Model):
 
 
 class LinkType(models.Model):
-    is_active = models.BooleanField(default=True)
+    is_active = models.BooleanField(default=True, help_text="True if link type is active.")
     name = models.CharField(max_length=32, help_text="Name of the link type")
 
     class Meta:
@@ -221,29 +228,31 @@ class Show(models.Model):
     created_at = models.DateTimeField(auto_now_add=True)
     created_by = models.CharField(max_length=150)
     default_playlist_id = models.IntegerField(blank=True, null=True)
-    description = models.TextField(blank=True)
-    email = models.EmailField(blank=True, null=True)
+    description = models.TextField(blank=True, help_text="Description of this show.")
+    email = models.EmailField(blank=True, null=True, help_text="Email address of this show.")
     funding_category = models.ForeignKey(
         FundingCategory, blank=True, null=True, on_delete=models.CASCADE, related_name="shows"
     )
     hosts = models.ManyToManyField(Host, blank=True, related_name="shows")
     image = models.ForeignKey(Image, null=True, on_delete=models.CASCADE, related_name="shows")
-    internal_note = models.TextField(blank=True)
-    is_active = models.BooleanField(default=True)
-    is_public = models.BooleanField(default=False)
+    internal_note = models.TextField(blank=True, help_text="Internal note for this show.")
+    is_active = models.BooleanField(default=True, help_text="True if this show is active.")
+    is_public = models.BooleanField(default=False, help_text="True if this show is public.")
     language = models.ManyToManyField(Language, blank=True, related_name="shows")
     # TODO: is this really necessary?
     logo = models.ForeignKey(
         Image, blank=True, null=True, on_delete=models.CASCADE, related_name="logo_shows"
     )
     music_focus = models.ManyToManyField(MusicFocus, blank=True, related_name="shows")
-    name = models.CharField(max_length=255)
+    name = models.CharField(max_length=255, help_text="Name of this Show.")
     owners = models.ManyToManyField(User, blank=True, related_name="shows")
     predecessor = models.ForeignKey(
         "self", blank=True, null=True, on_delete=models.CASCADE, related_name="successors"
     )
-    short_description = models.TextField()
-    slug = models.SlugField(blank=True, max_length=255, unique=True)
+    short_description = models.TextField(help_text="Short description of this show.")
+    slug = models.SlugField(
+        blank=True, max_length=255, unique=True, help_text="Slug of this show."
+    )
     topic = models.ManyToManyField(Topic, blank=True, related_name="shows")
     type = models.ForeignKey(
         Type, blank=True, null=True, on_delete=models.CASCADE, related_name="shows"
@@ -422,8 +431,8 @@ class Schedule(models.Model):
 
 class TimeSlot(models.Model):
     end = models.DateTimeField()
-    memo = models.TextField(blank=True)
-    playlist_id = models.IntegerField(null=True)
+    memo = models.TextField(blank=True, help_text="Memo for this timeslot.")
+    playlist_id = models.IntegerField(null=True, help_text="`Playlist` ID of this timeslot.")
     repetition_of = models.ForeignKey(
         "self", blank=True, null=True, on_delete=models.CASCADE, related_name="repetitions"
     )
@@ -461,18 +470,22 @@ class TimeSlot(models.Model):
 
 
 class Note(models.Model):
-    cba_id = models.IntegerField(blank=True, null=True)
-    content = models.TextField()
-    contributors = models.ManyToManyField(Host, related_name="notes")
+    cba_id = models.IntegerField(blank=True, null=True, help_text="CBA entry ID.")
+    content = models.TextField(help_text="Textual content of the note.")
+    contributors = models.ManyToManyField(
+        Host, related_name="notes", help_text="`Host` IDs contributing to this note."
+    )
     created_at = models.DateTimeField(auto_now_add=True)
     created_by = models.CharField(max_length=150)
     image = models.ForeignKey(Image, null=True, on_delete=models.CASCADE, related_name="notes")
     language = models.ManyToManyField(Language, blank=True, related_name="episodes")
     playlist = models.TextField(blank=True)
-    summary = models.TextField(blank=True)
+    summary = models.TextField(blank=True, help_text="Summary of the Note.")
     tags = models.JSONField(blank=True, default=list)
     timeslot = models.OneToOneField(TimeSlot, null=True, on_delete=models.SET_NULL, unique=True)
-    title = models.CharField(blank=True, default="", max_length=128)
+    title = models.CharField(
+        blank=True, default="", max_length=128, help_text="Title of the note."
+    )
     topic = models.ManyToManyField(Topic, blank=True, related_name="episodes")
     updated_at = models.DateTimeField(auto_now=True, blank=True, null=True)
     updated_by = models.CharField(blank=True, default="", max_length=150)
diff --git a/program/serializers.py b/program/serializers.py
index 7e9619817551fd3b3ec6e8ddfe2b800706abc4cb..ac67e886150abb69d03fa14da240f9051dc242bd 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -263,9 +263,13 @@ class Thumbnail(TypedDict):
 
 class ImageSerializer(serializers.ModelSerializer):
     license_id = serializers.PrimaryKeyRelatedField(
-        allow_null=True, queryset=License.objects.all(), required=False, source="license"
+        allow_null=True,
+        queryset=License.objects.all(),
+        required=False,
+        source="license",
+        help_text="`License` ID of this image.",
     )
-    ppoi = PPOIField(required=False)
+    ppoi = PPOIField(required=False, help_text="PPOI specifies the crop centerpoint of the image.")
     url = serializers.SerializerMethodField()
 
     @staticmethod
@@ -330,11 +334,21 @@ class ImageRenderSerializer(serializers.Serializer):
 
 class HostSerializer(serializers.ModelSerializer):
     image_id = serializers.PrimaryKeyRelatedField(
-        allow_null=True, queryset=Image.objects.all(), required=False, source="image"
+        allow_null=True,
+        queryset=Image.objects.all(),
+        required=False,
+        source="image",
+        help_text="`Image` id of the host.",
+    )
+    links = HostLinkSerializer(
+        many=True, required=False, help_text="Array of `HostLink` objects. Can be empty."
     )
-    links = HostLinkSerializer(many=True, required=False)
     owner_ids = serializers.PrimaryKeyRelatedField(
-        allow_null=True, many=True, queryset=User.objects.all(), source="owners"
+        allow_null=True,
+        many=True,
+        queryset=User.objects.all(),
+        source="owners",
+        help_text="`User` id(s) identifying this host.",
     )
 
     class Meta:
@@ -479,39 +493,74 @@ class ShowLinkSerializer(serializers.ModelSerializer):
 
 class ShowSerializer(serializers.HyperlinkedModelSerializer):
     category_ids = serializers.PrimaryKeyRelatedField(
-        many=True, queryset=Category.objects.all(), source="category"
+        many=True,
+        queryset=Category.objects.all(),
+        source="category",
+        help_text="Array of `Category` IDs.",
+    )
+    cba_series_id = serializers.IntegerField(
+        allow_null=True, required=False, help_text="CBA series ID."
+    )
+    default_playlist_id = serializers.IntegerField(
+        allow_null=True, required=False, help_text="Default `Playlist` ID for this show."
     )
-    cba_series_id = serializers.IntegerField(allow_null=True, required=False)
-    default_playlist_id = serializers.IntegerField(allow_null=True, required=False)
     funding_category_id = serializers.PrimaryKeyRelatedField(
-        queryset=FundingCategory.objects.all(), source="funding_category"
+        queryset=FundingCategory.objects.all(),
+        source="funding_category",
+        help_text="`FundingCategory` ID.",
     )
     host_ids = serializers.PrimaryKeyRelatedField(
-        many=True, queryset=Host.objects.all(), source="hosts"
+        many=True,
+        queryset=Host.objects.all(),
+        source="hosts",
+        help_text="`Host` IDs of this show.",
     )
     image_id = serializers.PrimaryKeyRelatedField(
-        allow_null=True, queryset=Image.objects.all(), required=False, source="image"
+        allow_null=True,
+        queryset=Image.objects.all(),
+        required=False,
+        source="image",
+        help_text="`Image` ID of this show.",
     )
     language_ids = serializers.PrimaryKeyRelatedField(
-        many=True, queryset=Language.objects.all(), source="language"
+        many=True,
+        queryset=Language.objects.all(),
+        source="language",
+        help_text="`Language` IDs of this show.",
     )
-    links = HostLinkSerializer(many=True, required=False)
+    links = HostLinkSerializer(many=True, required=False, help_text="Array of `Link` objects.")
     logo_id = serializers.PrimaryKeyRelatedField(
-        allow_null=True, queryset=Image.objects.all(), required=False, source="logo"
+        allow_null=True,
+        queryset=Image.objects.all(),
+        required=False,
+        source="logo",
+        help_text="`Image` ID of the logo of this show.",
     )
     music_focus_ids = serializers.PrimaryKeyRelatedField(
-        many=True, queryset=MusicFocus.objects.all(), source="music_focus"
+        many=True,
+        queryset=MusicFocus.objects.all(),
+        source="music_focus",
+        help_text="Array of `MusicFocus` IDs.",
     )
     owner_ids = serializers.PrimaryKeyRelatedField(
-        many=True, queryset=User.objects.all(), source="owners"
+        many=True,
+        queryset=User.objects.all(),
+        source="owners",
+        help_text="Array of `User` IDs owning this Show.",
     )
     predecessor_id = serializers.PrimaryKeyRelatedField(
-        allow_null=True, queryset=Show.objects.all(), required=False, source="predecessor"
+        allow_null=True,
+        queryset=Show.objects.all(),
+        required=False,
+        source="predecessor",
+        help_text="`Show` ID that predeceeded this one.",
     )
     topic_ids = serializers.PrimaryKeyRelatedField(
-        many=True, queryset=Topic.objects.all(), source="topic"
+        many=True, queryset=Topic.objects.all(), source="topic", help_text="Array of `Topic` IDs."
+    )
+    type_id = serializers.PrimaryKeyRelatedField(
+        queryset=Type.objects.all(), source="type", help_text="Array of `Type` IDs."
     )
-    type_id = serializers.PrimaryKeyRelatedField(queryset=Type.objects.all(), source="type")
 
     class Meta:
         model = Show
@@ -840,12 +889,18 @@ class DryRunTimeSlotSerializer(serializers.Serializer):
 
 
 class ScheduleCreateUpdateRequestSerializer(serializers.Serializer):
-    schedule = ScheduleInRequestSerializer()
+    schedule = ScheduleInRequestSerializer(help_text="`Schedule` object.")
     solutions = serializers.DictField(
-        child=serializers.ChoiceField(SOLUTION_CHOICES), required=False
+        child=serializers.ChoiceField(SOLUTION_CHOICES),
+        required=False,
+        help_text="Array of solution choices.",
+    )
+    notes = serializers.DictField(
+        child=serializers.IntegerField(), required=False, help_text="Array of `Note` objects."
+    )
+    playlists = serializers.DictField(
+        child=serializers.IntegerField(), required=False, help_text="Array of `Playlist` IDs."
     )
-    notes = serializers.DictField(child=serializers.IntegerField(), required=False)
-    playlists = serializers.DictField(child=serializers.IntegerField(), required=False)
 
 
 class ScheduleResponseSerializer(serializers.Serializer):
@@ -870,10 +925,17 @@ class TimeSlotSerializer(serializers.ModelSerializer):
     note_id = serializers.SerializerMethodField()
     show_id = serializers.SerializerMethodField()
     schedule_id = serializers.PrimaryKeyRelatedField(
-        queryset=Schedule.objects.all(), required=False, source="schedule"
+        queryset=Schedule.objects.all(),
+        required=False,
+        source="schedule",
+        help_text="`Schedule` ID of this timeslot.",
     )
     repetition_of_id = serializers.PrimaryKeyRelatedField(
-        allow_null=True, queryset=TimeSlot.objects.all(), required=False, source="repetition_of"
+        allow_null=True,
+        queryset=TimeSlot.objects.all(),
+        required=False,
+        source="repetition_of",
+        help_text="This timeslot is a repetition of `Timeslot` ID.",
     )
 
     class Meta:
@@ -934,9 +996,14 @@ class NoteSerializer(serializers.ModelSerializer):
         queryset=Host.objects.all(),
         required=False,
         source="contributors",
+        help_text="`Host` IDs that contributed to an episode.",
     )
     image_id = serializers.PrimaryKeyRelatedField(
-        queryset=Image.objects.all(), required=False, allow_null=True, source="image"
+        queryset=Image.objects.all(),
+        required=False,
+        allow_null=True,
+        source="image",
+        help_text="`Image` ID.",
     )
     language_ids = serializers.PrimaryKeyRelatedField(
         allow_null=True,
@@ -944,15 +1011,24 @@ class NoteSerializer(serializers.ModelSerializer):
         queryset=Language.objects.all(),
         required=False,
         source="language",
+        help_text="Array of `Language` IDs.",
     )
-    links = NoteLinkSerializer(many=True, required=False)
-    playlist_id = serializers.IntegerField(required=False)
-    tags = JSONSchemaField(tags_json_schema, required=False)
+    links = NoteLinkSerializer(many=True, required=False, help_text="Array of `Link` objects.")
+    playlist_id = serializers.IntegerField(required=False, help_text="Array of `Playlist` IDs.")
+    tags = JSONSchemaField(tags_json_schema, required=False, help_text="Tags of the Note.")
     timeslot_id = serializers.PrimaryKeyRelatedField(
-        queryset=TimeSlot.objects.all(), required=False, source="timeslot"
+        queryset=TimeSlot.objects.all(),
+        required=False,
+        source="timeslot",
+        help_text="`Timeslot` ID.",
     )
     topic_ids = serializers.PrimaryKeyRelatedField(
-        allow_null=True, many=True, queryset=Topic.objects.all(), required=False, source="topic"
+        allow_null=True,
+        many=True,
+        queryset=Topic.objects.all(),
+        required=False,
+        source="topic",
+        help_text="Array of `Topic`IDs.",
     )
 
     class Meta: