diff --git a/program/serializers.py b/program/serializers.py
index e666d9b7abc882cb1eb53d3934b7ec4bd19d0432..23f908e6a892a9a7f9dd587297a78a29824863df 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -481,6 +481,7 @@ class ImageSerializer(serializers.ModelSerializer):
         if "ppoi" in validated_data:
             instance.image.ppoi = validated_data.get("ppoi")
 
+        # TODO: extract as function to avoid repetition
         if "licensing" in validated_data:
             if licensing := validated_data.get("licensing"):
                 if instance.licensing:
@@ -1620,19 +1621,72 @@ class ApplicationStatePurgeSerializer(serializers.Serializer):
 
 
 class MediaSourceSerializer(serializers.ModelSerializer):
+    licensing = LicensingSerializer(
+        allow_null=True,
+        help_text="`Licensing` object.",
+        required=False,
+    )
     media_id = serializers.PrimaryKeyRelatedField(queryset=Media.objects.all(), source="media")
 
     def create(self, validated_data):
         validated_data.setdefault("order", 9999)
 
+        licensing_data = validated_data.pop("licensing", None)
+
         try:
-            return super().create(validated_data)
+            media_source = super().create(validated_data)
         except IntegrityError:
             raise exceptions.ValidationError(
                 code="media-source-file-id-or-uri-required",
                 detail="Media source must either have fileId or uri.",
             )
 
+        if licensing_data:
+            media_source.licensing = Licensing.objects.create(**licensing_data)
+            media_source.save()
+
+        return media_source
+
+    def update(self, instance, validated_data):
+        if "duration" in validated_data:
+            instance.duration = validated_data.get("duration")
+
+        if "file_id" in validated_data:
+            instance.file_id = validated_data.get("file_id")
+
+        if "media_id" in validated_data:
+            instance.media_id = validated_data.get("media_id")
+
+        if "url" in validated_data:
+            instance.url = validated_data.get("url")
+
+        # TODO: extract as function to avoid repetition
+        if "licensing" in validated_data:
+            if licensing := validated_data.get("licensing"):
+                if instance.licensing:
+                    instance.licensing.credits = licensing.get(
+                        "credits", instance.licensing.credits
+                    )
+                    instance.licensing.is_use_explicitly_granted_by_author = licensing.get(
+                        "is_use_explicitly_granted_by_author",
+                        instance.licensing.is_use_explicitly_granted_by_author,
+                    )
+                    instance.licensing.license = licensing.get(
+                        "license", instance.licensing.license
+                    )
+                else:
+                    instance.licensing = Licensing.objects.create(**licensing)
+
+                instance.licensing.save()
+            else:
+                licensing_pk = instance.licensing.pk
+                instance.licensing = None
+                Licensing.objects.get(pk=licensing_pk).delete()
+
+        instance.save()
+
+        return instance
+
     def validate(self, attrs):
         attrs = super().validate(attrs)
 
@@ -1651,6 +1705,7 @@ class MediaSourceSerializer(serializers.ModelSerializer):
         model = MediaSource
         fields = (
             "id",
+            "licensing",
             "media_id",
             "duration",
             "file_id",