diff --git a/program/serializers.py b/program/serializers.py
index bbae2a63899d1d5f737b7ea5781927bc993baf73..cf89e77e9e937a96b256f4a78bcdffcea25c09c0 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -1243,7 +1243,7 @@ class RadioSettingsSerializer(serializers.ModelSerializer):
 
 
 class BasicProgramEntrySerializer(serializers.Serializer):
-    id = serializers.CharField()
+    id = serializers.UUIDField()
     start = serializers.DateTimeField()
     end = serializers.DateTimeField()
     timeslot_id = serializers.IntegerField(allow_null=True, source="timeslot.id")
diff --git a/program/services.py b/program/services.py
index 77e57bb3e4d0027105d376648ddc0a0ec6781ef6..df7565b51019f9dd6e02f0cb729a13b9f2fe3cb8 100644
--- a/program/services.py
+++ b/program/services.py
@@ -18,6 +18,8 @@
 #
 
 import copy
+import hashlib
+import uuid
 from collections.abc import Iterator
 from datetime import datetime, time, timedelta
 
@@ -711,6 +713,12 @@ def get_fallback_show(raise_exceptions: bool = False):
     return fallback_show
 
 
+def uuid_from_string(data: str):
+    hash = hashlib.md5()
+    hash.update(data.encode())
+    return uuid.UUID(hex=hash.hexdigest(), version=4)
+
+
 def generate_program_entries(
     queryset: QuerySet[TimeSlot],
     *,
@@ -726,7 +734,7 @@ def generate_program_entries(
     def create_entry(
         starts_at: datetime, ends_at: datetime, show: Show, timeslot: TimeSlot | None = None
     ):
-        entry_id = f"{starts_at.isoformat()}...{ends_at.isoformat()}"
+        entry_id = uuid_from_string(f"{starts_at.isoformat()}...{ends_at.isoformat()}")
         if cut_at_range_boundaries:
             starts_at = max(starts_at, start)
             ends_at = min(ends_at, end)