diff --git a/conftest.py b/conftest.py
index 742475790cc8e42c45e187ab4c88144654233f53..7f5672d3dc54a4cedcb4ad9a477aad0454067858 100644
--- a/conftest.py
+++ b/conftest.py
@@ -106,7 +106,7 @@ def owned_image(image_file, common_user1) -> Image:
 
 @pytest.fixture
 def public_domain_license() -> License:
-    return LicenseFactory()
+    return LicenseFactory(identifier="pd", name="Public Domain")
 
 
 @pytest.fixture
@@ -350,3 +350,8 @@ def playlist(show) -> Playlist:
 @pytest.fixture
 def playlist_entry(playlist) -> PlaylistEntry:
     return PlaylistEntryFactory(playlist=playlist)
+
+
+@pytest.fixture
+def license_() -> License:
+    return LicenseFactory()
diff --git a/program/serializers.py b/program/serializers.py
index 51b27d858af63cb1ddc5a2cbbe17552a265fde82..e9481b51e98b1e21286d2a00ee5fbee7366fbc7f 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -117,6 +117,12 @@ class CBASerializer(serializers.ModelSerializer):
             "user_token",
         ) + read_only_fields
 
+    def to_representation(self, instance):
+        if not self.parent.context.get("request").user.is_authenticated:
+            return None
+
+        return super().to_representation(instance)
+
 
 class UserSerializer(serializers.ModelSerializer):
     is_privileged = serializers.SerializerMethodField()
@@ -404,6 +410,14 @@ class ProfileSerializer(serializers.ModelSerializer):
             "owner_ids",
         ) + read_only_fields
 
+    def to_representation(self, instance):
+        representation = super().to_representation(instance)
+
+        if not self.context.get("request").user.is_authenticated:
+            del representation["email"]
+
+        return representation
+
     def create(self, validated_data):
         """
         Create and return a new Profile instance, given the validated data.
@@ -640,6 +654,16 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
 
         return super().to_internal_value(data)
 
+    def to_representation(self, instance):
+        representation = super().to_representation(instance)
+
+        if not self.context.get("request").user.is_authenticated:
+            del representation["email"]
+        elif not self.context.get("request").user.has_perm("display__show__internal_note"):
+            del representation["internal_note"]
+
+        return representation
+
     def create(self, validated_data):
         """
         Create and return a new Show instance, given the validated data.
@@ -1011,6 +1035,14 @@ class TimeSlotSerializer(serializers.ModelSerializer):
     def get_end(obj) -> datetime:
         return obj.end.astimezone(tz=ZoneInfo(settings.TIME_ZONE))
 
+    def to_representation(self, instance):
+        representation = super().to_representation(instance)
+
+        if not self.context.get("request").user.is_authenticated:
+            del representation["memo"]
+
+        return representation
+
     def update(self, instance, validated_data):
         """Update and return an existing Show instance, given the validated data."""
 
diff --git a/program/tests/factories.py b/program/tests/factories.py
index 7f0fb629f6c5dce806f2c5ea15bae4c7c581b11a..6e008fb17daf2b35d8cc5d75ddd9d0adcf13b14d 100644
--- a/program/tests/factories.py
+++ b/program/tests/factories.py
@@ -74,7 +74,7 @@ class FundingCategoryFactory(DjangoModelFactory):
         model = FundingCategory
 
     name = Sequence(lambda n: "funding category %d" % n)
-    slug = Sequence(lambda n: "fc_%d" % n)
+    slug = Sequence(lambda n: "funding-category_%d" % n)
 
 
 class TypeFactory(DjangoModelFactory):
@@ -82,7 +82,7 @@ class TypeFactory(DjangoModelFactory):
         model = Type
 
     name = Sequence(lambda n: "type %d" % n)
-    slug = Sequence(lambda n: "t_%d" % n)
+    slug = Sequence(lambda n: "type_%d" % n)
 
 
 class ShowFactory(DjangoModelFactory):
@@ -90,7 +90,7 @@ class ShowFactory(DjangoModelFactory):
         model = Show
 
     name = Sequence(lambda n: "show %d" % n)
-    slug = Sequence(lambda n: "%s_d" % n)
+    slug = Sequence(lambda n: "show_%d" % n)
 
 
 class RRuleFactory(DjangoModelFactory):
@@ -119,8 +119,8 @@ class LicenseFactory(DjangoModelFactory):
     class Meta:
         model = License
 
-    identifier = "pd"
-    name = "Public Domain"
+    identifier = Sequence(lambda n: "identifier %d" % n)
+    name = Sequence(lambda n: "license %d" % n)
 
 
 class NoteFactory(DjangoModelFactory):
@@ -132,26 +132,41 @@ class CategoryFactory(DjangoModelFactory):
     class Meta:
         model = Category
 
+    description = Sequence(lambda n: "description %d" % n)
+    name = Sequence(lambda n: "category %d" % n)
+    slug = Sequence(lambda n: "category_%d" % n)
+    subtitle = Sequence(lambda n: "subtitle %d" % n)
+
 
 class LanguageFactory(DjangoModelFactory):
     class Meta:
         model = Language
 
+    name = Sequence(lambda n: "language %d" % n)
+
 
 class LinkTypeFactory(DjangoModelFactory):
     class Meta:
         model = LinkType
 
+    name = Sequence(lambda n: "language %d" % n)
+
 
 class MusicFocusFactory(DjangoModelFactory):
     class Meta:
         model = MusicFocus
 
+    name = Sequence(lambda n: "music focus %d" % n)
+    slug = Sequence(lambda n: "music-focus_%d" % n)
+
 
 class TopicFactory(DjangoModelFactory):
     class Meta:
         model = Topic
 
+    name = Sequence(lambda n: "topic %d" % n)
+    slug = Sequence(lambda n: "topic_%d" % n)
+
 
 class OwnerFactory(DjangoModelFactory):
     class Meta:
diff --git a/program/tests/test_categories.py b/program/tests/test_categories.py
new file mode 100644
index 0000000000000000000000000000000000000000..deba67ddb70d0f31a2dab3dd0104e16ace911542
--- /dev/null
+++ b/program/tests/test_categories.py
@@ -0,0 +1,100 @@
+import pytest
+
+from program.tests.factories import CategoryFactory
+
+pytestmark = pytest.mark.django_db
+
+
+def url(category=None):
+    return f"/api/v1/categories/{category.id}/" if category else "/api/v1/categories/"
+
+
+def test_create_category(admin_api_client):
+    data = {
+        "description": "DESCRIPTION",
+        "is_active": True,
+        "name": "NAME",
+        "slug": "category",
+        "subtitle": "SUBTITLE",
+    }
+
+    response = admin_api_client.post(url(), data)
+
+    assert response.status_code == 201
+
+    assert response.data["description"] == data["description"]
+    assert response.data["name"] == data["name"]
+    assert response.data["slug"] == data["slug"]
+    assert response.data["subtitle"] == data["subtitle"]
+
+
+def test_retrieve_category(common_api_client1, category):
+    response = common_api_client1.get(url(category=category))
+
+    assert response.status_code == 200
+
+    assert response.data["description"] == category.description
+    assert response.data["name"] == category.name
+    assert response.data["slug"] == category.slug
+    assert response.data["subtitle"] == category.subtitle
+
+
+def test_delete_category(admin_api_client, category):
+    response = admin_api_client.delete(url(category=category))
+
+    assert response.status_code == 204
+
+
+def test_list_categories(common_api_client1):
+    CATEGORIES = 3
+    CategoryFactory.create_batch(size=CATEGORIES)
+
+    response = common_api_client1.get(url())
+
+    assert response.status_code == 200
+    assert len(response.data) == CATEGORIES
+
+
+def test_update_description(admin_api_client, category):
+    update = {"description": "DESCRIPTION"}
+
+    response = admin_api_client.patch(url(category=category), update)
+
+    assert response.status_code == 200
+    assert response.data["description"] == update["description"]
+
+
+def test_update_is_active(admin_api_client, category):
+    update = {"is_active": False}
+
+    response = admin_api_client.patch(url(category=category), update)
+
+    assert response.status_code == 200
+    assert response.data["is_active"] == update["is_active"]
+
+
+def test_update_name(admin_api_client, category):
+    update = {"name": "NAME"}
+
+    response = admin_api_client.patch(url(category=category), update)
+
+    assert response.status_code == 200
+    assert response.data["name"] == update["name"]
+
+
+def test_update_slug(admin_api_client, category):
+    update = {"slug": "category"}
+
+    response = admin_api_client.patch(url(category=category), update)
+
+    assert response.status_code == 200
+    assert response.data["slug"] == update["slug"]
+
+
+def test_update_subtitle(admin_api_client, category):
+    update = {"subtitle": "SUBTITLE"}
+
+    response = admin_api_client.patch(url(category=category), update)
+
+    assert response.status_code == 200
+    assert response.data["subtitle"] == update["subtitle"]
diff --git a/program/tests/test_funding_categories.py b/program/tests/test_funding_categories.py
new file mode 100644
index 0000000000000000000000000000000000000000..bda1840a265cb47e837457f47e901017e7683f1c
--- /dev/null
+++ b/program/tests/test_funding_categories.py
@@ -0,0 +1,88 @@
+import pytest
+
+from program.tests.factories import FundingCategoryFactory
+
+pytestmark = pytest.mark.django_db
+
+
+def url(funding_category=None):
+    return (
+        f"/api/v1/funding-categories/{funding_category.id}/"
+        if funding_category
+        else "/api/v1/funding-categories/"
+    )
+
+
+def test_create_funding_category(admin_api_client):
+    data = {
+        "name": "NAME",
+        "is_active": True,
+        "slug": "funding-category",
+    }
+
+    response = admin_api_client.post(url(), data, format="json")
+
+    assert response.status_code == 201
+
+    assert response.data["is_active"] == data["is_active"]
+    assert response.data["name"] == data["name"]
+    assert response.data["slug"] == data["slug"]
+
+
+def test_retrieve_funding_category(common_api_client1, funding_category):
+    response = common_api_client1.get(url(funding_category=funding_category))
+
+    assert response.status_code == 200
+
+    assert response.data["is_active"] == funding_category.is_active
+    assert response.data["name"] == funding_category.name
+    assert response.data["slug"] == funding_category.slug
+
+
+def test_delete_funding_category(admin_api_client, funding_category):
+    response = admin_api_client.delete(url(funding_category=funding_category))
+
+    assert response.status_code == 204
+
+
+def test_list_funding_categories(common_api_client1):
+    FUNDING_CATEGORIES = 3
+    FundingCategoryFactory.create_batch(size=FUNDING_CATEGORIES)
+
+    response = common_api_client1.get(url())
+
+    assert response.status_code == 200
+    assert len(response.data) == FUNDING_CATEGORIES
+
+
+def test_update_is_active(admin_api_client, funding_category):
+    update = {
+        "is_active": False,
+    }
+
+    response = admin_api_client.patch(url(funding_category=funding_category), update)
+
+    assert response.status_code == 200
+    assert response.data["is_active"] == update["is_active"]
+
+
+def test_update_name(admin_api_client, funding_category):
+    update = {
+        "name": "NAME",
+    }
+
+    response = admin_api_client.patch(url(funding_category=funding_category), update)
+
+    assert response.status_code == 200
+    assert response.data["name"] == update["name"]
+
+
+def test_update_slug(admin_api_client, funding_category):
+    update = {
+        "slug": "funding-category",
+    }
+
+    response = admin_api_client.patch(url(funding_category=funding_category), update)
+
+    assert response.status_code == 200
+    assert response.data["slug"] == update["slug"]
diff --git a/program/tests/test_languages.py b/program/tests/test_languages.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e3a0b55e915bb938cc39ea33fa5daa22cdf8c87
--- /dev/null
+++ b/program/tests/test_languages.py
@@ -0,0 +1,65 @@
+import pytest
+
+from program.tests.factories import LanguageFactory
+
+pytestmark = pytest.mark.django_db
+
+
+def url(language=None):
+    return f"/api/v1/languages/{language.id}/" if language else "/api/v1/languages/"
+
+
+def test_create_language(admin_api_client):
+    data = {"is_active": True, "name": "NAME"}
+
+    response = admin_api_client.post(url(), data, format="json")
+
+    assert response.status_code == 201
+
+    assert response.data["is_active"] == data["is_active"]
+    assert response.data["name"] == data["name"]
+
+
+def test_retrieve_langauge(common_api_client1, language):
+    response = common_api_client1.get(url(language=language))
+
+    assert response.status_code == 200
+
+    assert response.data["is_active"] == language.is_active
+    assert response.data["name"] == language.name
+
+
+def test_delete_langauge(admin_api_client, language):
+    response = admin_api_client.delete(url(language=language))
+
+    assert response.status_code == 204
+
+
+def test_list_langauges(common_api_client1):
+    LANGUAGES = 3
+    LanguageFactory.create_batch(size=LANGUAGES)
+
+    response = common_api_client1.get(url())
+
+    print(response.data)
+
+    assert response.status_code == 200
+    assert len(response.data) == LANGUAGES
+
+
+def test_update_is_active(admin_api_client, language):
+    update = {"is_active": False}
+
+    response = admin_api_client.patch(url(language=language), update, format="json")
+
+    assert response.status_code == 200
+    assert response.data["is_active"] == update["is_active"]
+
+
+def test_update_name(admin_api_client, language):
+    update = {"name": "NAME"}
+
+    response = admin_api_client.patch(url(language=language), update)
+
+    assert response.status_code == 200
+    assert response.data["name"] == update["name"]
diff --git a/program/tests/test_licenses.py b/program/tests/test_licenses.py
new file mode 100644
index 0000000000000000000000000000000000000000..0aaa661310698a8c2e0831b9457c0972190953c8
--- /dev/null
+++ b/program/tests/test_licenses.py
@@ -0,0 +1,102 @@
+import pytest
+
+from program.tests.factories import LicenseFactory
+
+pytestmark = pytest.mark.django_db
+
+
+def url(license=None):
+    return f"/api/v1/licenses/{license.id}/" if license else "/api/v1/licenses/"
+
+
+def test_create_license(admin_api_client):
+    data = {"identifier": "IDENTIFIER", "name": "NAME"}
+
+    response = admin_api_client.post(url(), data)
+
+    assert response.status_code == 201
+
+    assert response.data["identifier"] == data["identifier"]
+    assert response.data["name"] == data["name"]
+
+
+def test_retrieve_license(common_api_client1, license_):
+    response = common_api_client1.get(url(license=license_))
+
+    assert response.status_code == 200
+
+    assert response.data["identifier"] == license_.identifier
+    assert response.data["name"] == license_.name
+
+
+def test_delete_license(admin_api_client, license_):
+    response = admin_api_client.delete(url(license=license_))
+
+    assert response.status_code == 204
+
+
+def test_list_licenses(common_api_client1):
+    LICENSES = 3
+    LicenseFactory.create_batch(size=LICENSES)
+
+    response = common_api_client1.get(url())
+
+    assert response.status_code == 200
+    assert len(response.data) == LICENSES
+
+
+def test_update_identifier(admin_api_client, license_):
+    update = {
+        "identifier": "IDENTIFIER",
+    }
+
+    response = admin_api_client.patch(url(license=license_), update)
+
+    assert response.status_code == 200
+
+    assert response.data["identifier"] == update["identifier"]
+
+
+def test_update_name(admin_api_client, license_):
+    update = {
+        "name": "NAME",
+    }
+
+    response = admin_api_client.patch(url(license=license_), update)
+
+    assert response.status_code == 200
+
+    assert response.data["name"] == update["name"]
+
+
+def test_update_needs_autor(admin_api_client, license_):
+    update = {"needs_author": False}
+
+    response = admin_api_client.patch(url(license=license_), update)
+
+    assert response.status_code == 200
+
+    assert response.data["needs_author"] == update["needs_author"]
+
+
+def test_update_requires_express_permission_for_publication(admin_api_client, license_):
+    update = {"requires_express_permission_for_publication": False}
+
+    response = admin_api_client.patch(url(license=license_), update)
+
+    assert response.status_code == 200
+
+    assert (
+        response.data["requires_express_permission_for_publication"]
+        == update["requires_express_permission_for_publication"]
+    )
+
+
+def test_update_url(admin_api_client, license_):
+    update = {"url": "https://aura.radio/"}
+
+    response = admin_api_client.patch(url(license=license_), update)
+
+    assert response.status_code == 200
+
+    assert response.data["url"] == update["url"]
diff --git a/program/tests/test_link_types.py b/program/tests/test_link_types.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd6a48bb219d95e225adef1dce640b610c07630f
--- /dev/null
+++ b/program/tests/test_link_types.py
@@ -0,0 +1,66 @@
+import pytest
+
+from program.tests.factories import LinkTypeFactory
+
+pytestmark = pytest.mark.django_db
+
+
+def url(link_type=None):
+    return f"/api/v1/link-types/{link_type.id}/" if link_type else "/api/v1/link-types/"
+
+
+def test_create_link_type(admin_api_client):
+    data = {
+        "is_active": True,
+        "name": "NAME",
+    }
+
+    response = admin_api_client.post(url(), data)
+
+    assert response.status_code == 201
+
+    assert response.data["is_active"] == data["is_active"]
+    assert response.data["name"] == data["name"]
+
+
+def test_retrieve_link_type(common_api_client1, link_type):
+    response = common_api_client1.get(url(link_type=link_type))
+
+    assert response.status_code == 200
+
+    assert response.data["is_active"] == link_type.is_active
+    assert response.data["name"] == link_type.name
+
+
+def test_delete_link_type(admin_api_client, link_type):
+    response = admin_api_client.delete(url(link_type=link_type))
+
+    assert response.status_code == 204
+
+
+def test_list_link_types(common_api_client1):
+    LINK_TYPES = 3
+    LinkTypeFactory.create_batch(size=LINK_TYPES)
+
+    response = common_api_client1.get(url())
+
+    assert response.status_code == 200
+    assert len(response.data) == LINK_TYPES
+
+
+def test_update_is_active(admin_api_client, link_type):
+    update = {"is_active": False}
+
+    response = admin_api_client.patch(url(link_type=link_type), update)
+
+    assert response.status_code == 200
+    assert response.data["is_active"] == update["is_active"]
+
+
+def test_update_name(admin_api_client, link_type):
+    update = {"name": "NAME"}
+
+    response = admin_api_client.patch(url(link_type=link_type), update)
+
+    assert response.status_code == 200
+    assert response.data["name"] == update["name"]
diff --git a/program/tests/test_music_focus.py b/program/tests/test_music_focus.py
new file mode 100644
index 0000000000000000000000000000000000000000..505728891a2dccc004a137718425553d20cd98d9
--- /dev/null
+++ b/program/tests/test_music_focus.py
@@ -0,0 +1,75 @@
+import pytest
+
+from program.tests.factories import MusicFocusFactory
+
+pytestmark = pytest.mark.django_db
+
+
+def url(music_focus=None):
+    return f"/api/v1/music-focus/{music_focus.id}/" if music_focus else "/api/v1/music-focus/"
+
+
+def test_create(admin_api_client):
+    data = {
+        "name": "NAME",
+        "slug": "music-focus",
+    }
+
+    response = admin_api_client.post(url(), data)
+
+    assert response.status_code == 201
+
+    assert response.data["name"] == data["name"]
+    assert response.data["slug"] == data["slug"]
+
+
+def test_retrieve_music_focus(common_api_client1, music_focus):
+    response = common_api_client1.get(url(music_focus=music_focus))
+
+    assert response.status_code == 200
+
+    assert response.data["name"] == music_focus.name
+    assert response.data["slug"] == music_focus.slug
+
+
+def test_delete(admin_api_client, music_focus):
+    response = admin_api_client.delete(url(music_focus=music_focus))
+
+    assert response.status_code == 204
+
+
+def test_list(common_api_client1):
+    MUSIC_FOCUS = 3
+    MusicFocusFactory.create_batch(size=MUSIC_FOCUS)
+
+    response = common_api_client1.get(url())
+
+    assert response.status_code == 200
+    assert len(response.data) == MUSIC_FOCUS
+
+
+def test_update_is_active(admin_api_client, music_focus):
+    update = {"is_active": False}
+
+    response = admin_api_client.patch(url(music_focus=music_focus), update)
+
+    assert response.status_code == 200
+    assert response.data["is_active"] is update["is_active"]
+
+
+def test_update_name(admin_api_client, music_focus):
+    update = {"name": "NAME"}
+
+    response = admin_api_client.patch(url(music_focus=music_focus), update)
+
+    assert response.status_code == 200
+    assert response.data["name"] == update["name"]
+
+
+def test_update_slug(admin_api_client, music_focus):
+    update = {"slug": "music-focus"}
+
+    response = admin_api_client.patch(url(music_focus=music_focus), update)
+
+    assert response.status_code == 200
+    assert response.data["slug"] == update["slug"]
diff --git a/program/tests/test_profiles.py b/program/tests/test_profiles.py
index 5749be76076f10d2bd4689c7de355cf498931343..dd3f676c7911f4c05c3767c8ff07cc5354d010ea 100644
--- a/program/tests/test_profiles.py
+++ b/program/tests/test_profiles.py
@@ -99,3 +99,13 @@ def test_update_profile_forbidden_for_common_user(common_api_client1, profile):
     response = common_api_client1.put(url(profile), data=update)
 
     assert response.status_code == 403
+
+
+def test_redacted_fields_for_unauthenticated_requests(api_client, profile):
+    response = api_client.get(url(profile))
+    data = response.json()
+
+    assert response.status_code == 200
+
+    assert "email" not in data
+    assert "cba" not in data
diff --git a/program/tests/test_shows.py b/program/tests/test_shows.py
index 79ed7bde14fcaa3f266d0892e802835b2c238946..e0e1855c48d6217e5a6afc26c39995c87cc997a4 100644
--- a/program/tests/test_shows.py
+++ b/program/tests/test_shows.py
@@ -199,3 +199,22 @@ def test_clear_default_playlist_id(admin_api_client, show, default_playlist):
     assert response.status_code == 200
 
     assert response.data["default_playlist_id"] == update["default_playlist_id"]
+
+
+def test_redacted_fields_for_unauthenticated_requests(api_client, show):
+    response = api_client.get(url(show))
+    data = response.json()
+
+    assert response.status_code == 200
+
+    assert "email" not in data
+    assert "internal_note" not in data
+
+
+def test_redacted_fields_for_common_user(common_api_client1, show):
+    response = common_api_client1.get(url(show))
+    data = response.json()
+
+    assert response.status_code == 200
+
+    assert "internal_note" not in data
diff --git a/program/tests/test_timeslots.py b/program/tests/test_timeslots.py
index b7bc282607802b6cade6bdbc8c6096cb4e1a2342..a2f4ad70eed84f68d7e2b9e6d5aea361b908bfb8 100644
--- a/program/tests/test_timeslots.py
+++ b/program/tests/test_timeslots.py
@@ -92,3 +92,12 @@ def test_update_timeslot_forbidden_as_unauthenticated(api_client, once_timeslot)
     response = api_client.put(url(timeslot=once_timeslot), data=update)
 
     assert response.status_code == 403
+
+
+def test_redacted_field_for_unauthenticated_requests(api_client, once_timeslot):
+    response = api_client.get(url(timeslot=once_timeslot))
+    data = response.json()
+
+    assert response.status_code == 200
+
+    assert "memo" not in data
diff --git a/program/tests/test_topics.py b/program/tests/test_topics.py
new file mode 100644
index 0000000000000000000000000000000000000000..d03c4b3de22316917eeb148f9b06ad699248c888
--- /dev/null
+++ b/program/tests/test_topics.py
@@ -0,0 +1,75 @@
+import pytest
+
+from program.tests.factories import TopicFactory
+
+pytestmark = pytest.mark.django_db
+
+
+def url(topic=None):
+    return f"/api/v1/topics/{topic.id}/" if topic else "/api/v1/topics/"
+
+
+def test_create_topic(admin_api_client):
+    data = {
+        "name": "NAME",
+        "slug": "topic",
+    }
+
+    response = admin_api_client.post(url(), data)
+
+    assert response.status_code == 201
+
+    assert response.data["name"] == data["name"]
+    assert response.data["slug"] == data["slug"]
+
+
+def test_retrieve(common_api_client1, topic):
+    response = common_api_client1.get(url(topic=topic))
+
+    assert response.status_code == 200
+
+    assert response.data["name"] == topic.name
+    assert response.data["slug"] == topic.slug
+
+
+def test_delete(admin_api_client, topic):
+    response = admin_api_client.delete(url(topic=topic))
+
+    assert response.status_code == 204
+
+
+def test_list(common_api_client1):
+    TOPICS = 3
+    TopicFactory.create_batch(size=TOPICS)
+
+    response = common_api_client1.get(url())
+
+    assert response.status_code == 200
+    assert len(response.data) == TOPICS
+
+
+def test_update_is_active(admin_api_client, topic):
+    update = {"is_active": False}
+
+    response = admin_api_client.patch(url(topic=topic), update)
+
+    assert response.status_code == 200
+    assert response.data["is_active"] is update["is_active"]
+
+
+def test_update_name(admin_api_client, topic):
+    update = {"name": "NAME"}
+
+    response = admin_api_client.patch(url(topic=topic), update)
+
+    assert response.status_code == 200
+    assert response.data["name"] == update["name"]
+
+
+def test_update_slug(admin_api_client, topic):
+    update = {"slug": "topic"}
+
+    response = admin_api_client.patch(url(topic=topic), update)
+
+    assert response.status_code == 200
+    assert response.data["slug"] == update["slug"]
diff --git a/program/tests/test_types.py b/program/tests/test_types.py
new file mode 100644
index 0000000000000000000000000000000000000000..d00bfd30f0a80be3bdf9602ecec88bf058d85b64
--- /dev/null
+++ b/program/tests/test_types.py
@@ -0,0 +1,75 @@
+import pytest
+
+from program.tests.factories import TypeFactory
+
+pytestmark = pytest.mark.django_db
+
+
+def url(type=None):
+    return f"/api/v1/types/{type.id}/" if type else "/api/v1/types/"
+
+
+def test_create(admin_api_client):
+    data = {
+        "name": "NAME",
+        "slug": "type",
+    }
+
+    response = admin_api_client.post(url(), data)
+
+    assert response.status_code == 201
+
+    assert response.data["name"] == data["name"]
+    assert response.data["slug"] == data["slug"]
+
+
+def test_retrieve(common_api_client1, type_):
+    response = common_api_client1.get(url(type_))
+
+    assert response.status_code == 200
+
+    assert response.data["name"] == type_.name
+    assert response.data["slug"] == type_.slug
+
+
+def test_delete(admin_api_client, type_):
+    response = admin_api_client.delete(url(type=type_))
+
+    assert response.status_code == 204
+
+
+def test_list(common_api_client1):
+    TYPES = 3
+    TypeFactory.create_batch(size=TYPES)
+
+    response = common_api_client1.get(url())
+
+    assert response.status_code == 200
+    assert len(response.data) == TYPES
+
+
+def test_update_is_active(admin_api_client, type_):
+    update = {"is_active": False}
+
+    response = admin_api_client.patch(url(type=type_), update)
+
+    assert response.status_code == 200
+    assert response.data["is_active"] is update["is_active"]
+
+
+def test_update_name(admin_api_client, type_):
+    update = {"name": "NAME"}
+
+    response = admin_api_client.patch(url(type=type_), update)
+
+    assert response.status_code == 200
+    assert response.data["name"] == update["name"]
+
+
+def test_update_slug(admin_api_client, type_):
+    update = {"slug": "topic"}
+
+    response = admin_api_client.patch(url(type=type_), update)
+
+    assert response.status_code == 200
+    assert response.data["slug"] == update["slug"]
diff --git a/program/views.py b/program/views.py
index 9062ba7924dde9595dba878db11aab59a96229bb..ce6c317c52f4e616644831659e0f0a231c80fb84 100644
--- a/program/views.py
+++ b/program/views.py
@@ -580,10 +580,14 @@ class APIUserViewSet(
         else:
             return User.objects.filter(pk=user.id)
 
+    def get_serializer_context(self):
+        context = super().get_serializer_context()
+        context.update({"request": self.request})
+
+        return context
+
     def create(self, request, *args, **kwargs):
         serializer = UserSerializer(
-            # FIXME: the method get_serializer_context should be used but it does seem to get lost
-            context={"request": request},  # the serializer needs the request in the context
             data=request.data,
         )
 
@@ -713,10 +717,15 @@ class APIShowViewSet(viewsets.ModelViewSet):
         self.check_object_permissions(self.request, obj)
         return obj
 
+    def get_serializer_context(self):
+        context = super().get_serializer_context()
+        context.update({"request": self.request})
+
+        return context
+
     def create(self, request, *args, **kwargs):
         serializer = ShowSerializer(
-            # FIXME: the method get_serializer_context should be used but it does seem to get lost
-            context={"request": request},  # the serializer needs the request in the context
+            context={"request": self.request},  # FIXME: this is somehow needed by the tests
             data=request.data,
         )
 
@@ -736,8 +745,7 @@ class APIShowViewSet(viewsets.ModelViewSet):
         partial = kwargs.get("partial", False)
         show = self.get_object()
         serializer = ShowSerializer(
-            # FIXME: the method get_serializer_context should be used but it does seem to get lost
-            context={"request": request},  # the serializer needs the request in the context
+            context={"request": self.request},  # FIXME: this is somehow needed by the tests
             data=request.data,
             instance=show,
             partial=partial,
@@ -1332,6 +1340,12 @@ class APITimeSlotViewSet(
     queryset = TimeSlot.objects.all().order_by("-start")
     serializer_class = TimeSlotSerializer
 
+    def get_serializer_context(self):
+        context = super().get_serializer_context()
+        context.update({"request": self.request})
+
+        return context
+
     def update(self, request, *args, **kwargs):
         show_pk = get_values(self.kwargs, "show_pk")
         timeslot = self.get_object()
@@ -1485,10 +1499,15 @@ class APIProfileViewSet(ActiveFilterMixin, viewsets.ModelViewSet):
     filter_backends = [drf_filters.SearchFilter]
     search_fields = ["name", "email"]
 
+    def get_serializer_context(self):
+        context = super().get_serializer_context()
+        context.update({"request": self.request})
+
+        return context
+
     def create(self, request, *args, **kwargs):
         serializer = ProfileSerializer(
-            # FIXME: the method get_serializer_context should be used but it does seem to get lost
-            context={"request": request},  # the serializer needs the request in the context
+            context={"request": self.request},  # FIXME: this is somehow needed by the tests
             data=request.data,
         )
         if serializer.is_valid(raise_exception=True):
@@ -1500,8 +1519,7 @@ class APIProfileViewSet(ActiveFilterMixin, viewsets.ModelViewSet):
         profile = self.get_object()
 
         serializer = ProfileSerializer(
-            # FIXME: the method get_serializer_context should be used but it does seem to get lost
-            context={"request": request},  # the serializer needs the request in the context
+            context={"request": self.request},  # FIXME: this is somehow needed by the tests
             data=request.data,
             instance=profile,
             partial=partial,