diff --git a/scipost_django/journals/serializers/publication.py b/scipost_django/api/serializers.py
similarity index 63%
rename from scipost_django/journals/serializers/publication.py
rename to scipost_django/api/serializers.py
index f39f839d4097f69589075e92184ad2cfbdfe2030..b452a3916d88b08bf59f63d3564220e2200e873c 100644
--- a/scipost_django/journals/serializers/publication.py
+++ b/scipost_django/api/serializers.py
@@ -4,22 +4,12 @@ __license__ = "AGPL v3"
 
 from rest_framework import serializers
 
-from ..models import Publication
 
-
-class PublicationSerializer(serializers.ModelSerializer):
-    url = serializers.URLField(source='get_absolute_url')
-
-    class Meta:
-        model = Publication
-        fields = [
-            'title',
-            'author_list',
-            'abstract',
-            'doi_label',
-            'publication_date',
-            'url'
-        ]
+class DynamicFieldsModelSerializer(serializers.ModelSerializer):
+    """
+    A ModelSerializer that takes an additional `fields` argument that
+    controls which fields should be displayed (from DRF docs).
+    """
 
     def __init__(self, *args, **kwargs):
         # Don't pass the 'fields' arg up to the superclass
diff --git a/scipost_django/api/urls.py b/scipost_django/api/urls.py
index 197189b2581e98517a4ebb89f1df79dfea56bf19..6628299641c1fb431d41279d9aede130082e6fa2 100644
--- a/scipost_django/api/urls.py
+++ b/scipost_django/api/urls.py
@@ -7,8 +7,15 @@ from django.urls import include, path
 
 from rest_framework import routers
 
-from journals.viewsets import PublicationViewSet, PubFractionViewSet
-from organizations.api.viewsets import OrganizationViewSet, OrganizationNAPViewSet
+from journals.api.viewsets import (
+    PublicationPublicAPIViewSet,
+    PubFractionPublicAPIViewSet
+)
+from organizations.api.viewsets import (
+    OrganizationViewSet,
+    OrganizationNAPViewSet
+)
+# The non-api viewsets below should be deprecated:
 from submissions.viewsets import SubmissionViewSet
 
 # Next two: old style, to be deprecated:
@@ -23,8 +30,8 @@ app_name = 'api'
 router = routers.SimpleRouter()
 
 # journals
-router.register('publications', PublicationViewSet)
-router.register('pubfractions', PubFractionViewSet)
+router.register('publications', PublicationPublicAPIViewSet)
+router.register('pubfractions', PubFractionPublicAPIViewSet)
 
 # organizations
 router.register('organizations', OrganizationViewSet)
@@ -49,6 +56,6 @@ urlpatterns += [
         name='omniauth_userinfo'
     ),
     path('finances/', include('finances.api.urls')),
-    path('journals/', include('journals.api.urls')),
+    path('deprec/journals/', include('journals.api.urls')), # TODO remove
 
 ]
diff --git a/scipost_django/journals/api/filtersets/__init__.py b/scipost_django/journals/api/filtersets/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..fbe9d05ce4e480b3ab92b4efd26bd1c16266e317
--- /dev/null
+++ b/scipost_django/journals/api/filtersets/__init__.py
@@ -0,0 +1,7 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from .publication import PublicationPublicFilterSet
+
+from .pubfraction import PubFractionPublicFilterSet
diff --git a/scipost_django/journals/api/filtersets/pubfraction.py b/scipost_django/journals/api/filtersets/pubfraction.py
new file mode 100644
index 0000000000000000000000000000000000000000..c91c9abcb361a1b8086f785f4ee003fd6f04bb34
--- /dev/null
+++ b/scipost_django/journals/api/filtersets/pubfraction.py
@@ -0,0 +1,22 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django_filters import rest_framework as df_filters
+
+from journals.models import OrgPubFraction
+
+
+class PubFractionPublicFilterSet(df_filters.FilterSet):
+    class Meta:
+        model = OrgPubFraction
+        fields = {
+            'organization__name': ['icontains', 'istartswith', 'exact'],
+            'organization__country': ['exact',],
+            'publication__publication_date': [
+                'year', 'month', 'exact',
+                'year__gte', 'year__lte', 'year__range',
+                'gte', 'lte', 'range'
+            ],
+            'fraction': ['gte', 'lte', 'exact']
+        }
diff --git a/scipost_django/journals/viewsets/publication.py b/scipost_django/journals/api/filtersets/publication.py
similarity index 50%
rename from scipost_django/journals/viewsets/publication.py
rename to scipost_django/journals/api/filtersets/publication.py
index be45b3ebc0794f0d114d74d79ff27863c9180c15..9ce951dd79da15534e6d5166980a1c3297ec6992 100644
--- a/scipost_django/journals/viewsets/publication.py
+++ b/scipost_django/journals/api/filtersets/publication.py
@@ -4,16 +4,10 @@ __license__ = "AGPL v3"
 
 from django_filters import rest_framework as df_filters
 
-from rest_framework import viewsets
-from rest_framework.permissions import AllowAny
+from ...models import Publication
 
-from api.viewsets.mixins import FilteringOptionsActionMixin
 
-from ..models import Publication
-from ..serializers import PublicationSerializer
-
-
-class PublicationFilterSet(df_filters.FilterSet):
+class PublicationPublicFilterSet(df_filters.FilterSet):
     class Meta:
         model = Publication
         fields = {
@@ -31,19 +25,3 @@ class PublicationFilterSet(df_filters.FilterSet):
             'specialties__name': ['icontains',],
             'topics__name': ['icontains',],
         }
-
-
-class PublicationViewSet(FilteringOptionsActionMixin,
-                         viewsets.ReadOnlyModelViewSet):
-    queryset = Publication.objects.published().order_by('-publication_date')
-    permission_classes = [AllowAny,]
-    serializer_class = PublicationSerializer
-    search_fields = ['title', 'author_list', 'abstract', 'doi_label']
-    ordering_fields = ['publication_date',]
-    filterset_class = PublicationFilterSet
-    default_filtering_fields = [
-        'title__icontains',
-        'author_list__icontains',
-        'abstract__icontains',
-        'doi_label__icontains'
-    ]
diff --git a/scipost_django/journals/api/serializers/__init__.py b/scipost_django/journals/api/serializers/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..747acc8370e27df4a56083028de6caf5c72a9aef
--- /dev/null
+++ b/scipost_django/journals/api/serializers/__init__.py
@@ -0,0 +1,7 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from .publication import PublicationPublicSerializer
+
+from .pubfraction import PubFractionPublicSerializer
diff --git a/scipost_django/journals/serializers/pubfraction.py b/scipost_django/journals/api/serializers/pubfraction.py
similarity index 72%
rename from scipost_django/journals/serializers/pubfraction.py
rename to scipost_django/journals/api/serializers/pubfraction.py
index 9131a088816b6215d8ce7040b943824087c498dc..7b19fbe932a686a4b7d758061b7f0b12334e48a9 100644
--- a/scipost_django/journals/serializers/pubfraction.py
+++ b/scipost_django/journals/api/serializers/pubfraction.py
@@ -4,16 +4,16 @@ __license__ = "AGPL v3"
 
 from rest_framework import serializers
 
-from ..models import OrgPubFraction
-from journals.serializers import PublicationSerializer
+from journals.models import OrgPubFraction
+from journals.api.serializers import PublicationPublicSerializer
 from organizations.api.serializers import OrganizationSerializer
 
 
-class PubFractionSerializer(serializers.ModelSerializer):
+class PubFractionPublicSerializer(serializers.ModelSerializer):
     organization = OrganizationSerializer(
         fields=['url', 'name', 'acronym', 'country']
     )
-    publication = PublicationSerializer(
+    publication = PublicationPublicSerializer(
         fields=[
             'url',
             'title', 'author_list',
diff --git a/scipost_django/journals/api/serializers/publication.py b/scipost_django/journals/api/serializers/publication.py
new file mode 100644
index 0000000000000000000000000000000000000000..de9a56f77e89dc4026f00c79f249701e3299cb88
--- /dev/null
+++ b/scipost_django/journals/api/serializers/publication.py
@@ -0,0 +1,23 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from rest_framework import serializers
+
+from api.serializers import DynamicFieldsModelSerializer
+from ...models import Publication
+
+
+class PublicationPublicSerializer(DynamicFieldsModelSerializer):
+    url = serializers.URLField(source='get_absolute_url')
+
+    class Meta:
+        model = Publication
+        fields = [
+            'title',
+            'author_list',
+            'abstract',
+            'doi_label',
+            'publication_date',
+            'url'
+        ]
diff --git a/scipost_django/journals/api/serializers.py b/scipost_django/journals/api/serializers_deprec.py
similarity index 100%
rename from scipost_django/journals/api/serializers.py
rename to scipost_django/journals/api/serializers_deprec.py
diff --git a/scipost_django/journals/api/views.py b/scipost_django/journals/api/views.py
index d2b96c35d49b0943e9b2ed365842099aa0d4e60e..9e07141233e1ca8ca0ffb35e336b2fe2aadd1bed 100644
--- a/scipost_django/journals/api/views.py
+++ b/scipost_django/journals/api/views.py
@@ -7,7 +7,7 @@ from rest_framework.generics import ListAPIView, RetrieveAPIView
 from django.db.models import Sum
 
 from ..models import Publication, OrgPubFraction
-from .serializers import PublicationSerializer, OrgPubFractionSerializer
+from .serializers_deprec import PublicationSerializer, OrgPubFractionSerializer
 
 
 class PublicationListAPIView(ListAPIView):
diff --git a/scipost_django/journals/api/viewsets/__init__.py b/scipost_django/journals/api/viewsets/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..74962af468817eb6643aabfea185da54c31b9334
--- /dev/null
+++ b/scipost_django/journals/api/viewsets/__init__.py
@@ -0,0 +1,7 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from .publication import PublicationPublicAPIViewSet
+
+from .pubfraction import PubFractionPublicAPIViewSet
diff --git a/scipost_django/journals/api/viewsets/pubfraction.py b/scipost_django/journals/api/viewsets/pubfraction.py
new file mode 100644
index 0000000000000000000000000000000000000000..ac63fec64322bd9f0ae994098a865f5717f34527
--- /dev/null
+++ b/scipost_django/journals/api/viewsets/pubfraction.py
@@ -0,0 +1,33 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django_filters import rest_framework as df_filters
+
+from rest_framework import viewsets
+from rest_framework.permissions import AllowAny
+
+from api.viewsets.mixins import FilteringOptionsActionMixin
+
+from journals.models import OrgPubFraction
+from journals.api.serializers import PubFractionPublicSerializer
+
+from journals.api.filtersets import PubFractionPublicFilterSet
+
+
+class PubFractionPublicAPIViewSet(
+        FilteringOptionsActionMixin,
+        viewsets.ReadOnlyModelViewSet):
+    queryset = OrgPubFraction.objects.all()
+    permission_classes = [AllowAny,]
+    serializer_class = PubFractionPublicSerializer
+    search_fields = [
+        'organization__name',
+        'publication__publication_date__year'
+    ]
+    ordering_fields = ['-publication_date',]
+    filterset_class = PubFractionPublicFilterSet
+    default_filtering_fields = [
+        'organization__name__icontains',
+        'publication__publication_date__year__exact',
+    ]
diff --git a/scipost_django/journals/api/viewsets/publication.py b/scipost_django/journals/api/viewsets/publication.py
new file mode 100644
index 0000000000000000000000000000000000000000..8200b00ee6c0b084ba979f90f10f512f00f4fc75
--- /dev/null
+++ b/scipost_django/journals/api/viewsets/publication.py
@@ -0,0 +1,31 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django_filters import rest_framework as df_filters
+
+from rest_framework import viewsets
+from rest_framework.permissions import AllowAny
+
+from api.viewsets.mixins import FilteringOptionsActionMixin
+
+from journals.models import Publication
+from journals.api.filtersets import PublicationPublicFilterSet
+from journals.api.serializers import PublicationPublicSerializer
+
+
+class PublicationPublicAPIViewSet(
+        FilteringOptionsActionMixin,
+        viewsets.ReadOnlyModelViewSet):
+    queryset = Publication.objects.published()
+    permission_classes = [AllowAny,]
+    serializer_class = PublicationPublicSerializer
+    search_fields = ['title', 'author_list', 'abstract', 'doi_label']
+    ordering_fields = ['publication_date',]
+    filterset_class = PublicationPublicFilterSet
+    default_filtering_fields = [
+        'title__icontains',
+        'author_list__icontains',
+        'abstract__icontains',
+        'doi_label__icontains'
+    ]
diff --git a/scipost_django/journals/serializers/__init__.py b/scipost_django/journals/serializers/__init__.py
deleted file mode 100644
index 1281e63f6b8d53fdd0cba2c6b9ded4e113279f3e..0000000000000000000000000000000000000000
--- a/scipost_django/journals/serializers/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
-__license__ = "AGPL v3"
-
-
-from .publication import PublicationSerializer
-
-from .pubfraction import PubFractionSerializer
diff --git a/scipost_django/journals/viewsets/__init__.py b/scipost_django/journals/viewsets/__init__.py
deleted file mode 100644
index 1087946c3ee5bccaaa2f2b2c38c900be4669626d..0000000000000000000000000000000000000000
--- a/scipost_django/journals/viewsets/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
-__license__ = "AGPL v3"
-
-
-from .publication import PublicationViewSet
-from .pubfraction import PubFractionViewSet
diff --git a/scipost_django/journals/viewsets/pubfraction.py b/scipost_django/journals/viewsets/pubfraction.py
deleted file mode 100644
index 8af8e83f7ab704188892b470f3da07d3a60f04e9..0000000000000000000000000000000000000000
--- a/scipost_django/journals/viewsets/pubfraction.py
+++ /dev/null
@@ -1,45 +0,0 @@
-__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
-__license__ = "AGPL v3"
-
-
-from django_filters import rest_framework as df_filters
-
-from rest_framework import viewsets
-from rest_framework.permissions import AllowAny
-
-from api.viewsets.mixins import FilteringOptionsActionMixin
-
-from ..models import OrgPubFraction
-from ..serializers import PubFractionSerializer
-
-
-class PubFractionFilterSet(df_filters.FilterSet):
-    class Meta:
-        model = OrgPubFraction
-        fields = {
-            'organization__name': ['icontains', 'istartswith', 'exact'],
-            'organization__country': ['exact',],
-            'publication__publication_date': [
-                'year', 'month', 'exact',
-                'year__gte', 'year__lte', 'year__range',
-                'gte', 'lte', 'range'
-            ],
-            'fraction': ['gte', 'lte', 'exact']
-        }
-
-
-class PubFractionViewSet(FilteringOptionsActionMixin,
-                         viewsets.ReadOnlyModelViewSet):
-    queryset = OrgPubFraction.objects.all()
-    permission_classes = [AllowAny,]
-    serializer_class = PubFractionSerializer
-    search_fields = [
-        'organization__name',
-        'publication__publication_date__year'
-    ]
-    ordering_fields = ['-publication_date',]
-    filterset_class = PubFractionFilterSet
-    default_filtering_fields = [
-        'organization__name__icontains',
-        'publication__publication_date__year__exact',
-    ]
diff --git a/scipost_django/organizations/api/viewsets.py b/scipost_django/organizations/api/viewsets.py
index ce2bb0a96dbe372d5c40eab3e67ea59a93b3ffcb..5c72d17d561978eb72c660b0d3330ff015e38b36 100644
--- a/scipost_django/organizations/api/viewsets.py
+++ b/scipost_django/organizations/api/viewsets.py
@@ -16,7 +16,7 @@ from rest_framework_csv import renderers as r
 from api.viewsets.mixins import FilteringOptionsActionMixin
 
 from ..models import Organization
-from journals.api.serializers import OrgPubFractionSerializer
+from journals.api.serializers import PubFractionPublicSerializer
 from .serializers import (
     OrganizationSerializer,
     OrganizationNAPSerializer,
@@ -53,7 +53,7 @@ class OrganizationViewSet(FilteringOptionsActionMixin,
     @action(detail=True)
     def pubfractions(self, request, pk=None):
         pubfractions = self.get_object().pubfractions.all()
-        serializer = OrgPubFractionSerializer(
+        serializer = PubFractionPublicSerializer(
             pubfractions,
             many=True,
             context={'request': self.request}