diff --git a/program/views.py b/program/views.py
index a47f5cb13cc52e5b54b0c3431acc527af487a110..870da0c99c054940155ecc1892c1ced1a64c3458 100644
--- a/program/views.py
+++ b/program/views.py
@@ -54,6 +54,7 @@ from program.models import (
     LinkType,
     MusicFocus,
     Note,
+    Playlist,
     Profile,
     RadioSettings,
     RRule,
@@ -79,6 +80,7 @@ from program.serializers import (
     LinkTypeSerializer,
     MusicFocusSerializer,
     NoteSerializer,
+    PlaylistSerializer,
     PlayoutProgramEntrySerializer,
     ProfileSerializer,
     RadioSettingsSerializer,
@@ -1630,3 +1632,26 @@ class APIApplicationStateView(TestOperationViewMixin, views.APIView):
             invert_selection=params.validated_data["invert_selection"],
         )
         return Response(status=status.HTTP_200_OK, data=deleted)
+
+
+class APIPlaylistViewSet(viewsets.ModelViewSet):
+    serializer_class = PlaylistSerializer
+
+    def get_queryset(self):
+        """The queryset is empty if the request is not authenticated, it contains all the playlists
+        if the request method is safe or if the requesting user has the `create_playlist` or the
+        `update_playlist`, otherwise it only contains playlists for shows owned by the
+        requesting user."""
+
+        user = self.request.user
+
+        if not user.is_authenticated:
+            return Playlist.objects.none()
+        elif (
+            self.request.method in permissions.SAFE_METHODS
+            or user.has_perm("program.create_playlist")
+            or user.has_perm("program.update_playlist")
+        ):
+            return Playlist.objects.all()
+        else:
+            return Playlist.objects.filter(show__owners=user)