diff --git a/apps/activity/api/views.py b/apps/activity/api/views.py
index 6a6c024ef0d4ef89dbff763dd0a4ce529699c6b8..4ee2194d06c38cad2726feb8536c149248aa336b 100644
--- a/apps/activity/api/views.py
+++ b/apps/activity/api/views.py
@@ -1,7 +1,8 @@
 # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
 # SPDX-License-Identifier: GPL-3.0-or-later
-
+from django_filters.rest_framework import DjangoFilterBackend
 from rest_framework import viewsets
+from rest_framework.filters import SearchFilter
 
 from .serializers import ActivityTypeSerializer, ActivitySerializer, GuestSerializer
 from ..models import ActivityType, Activity, Guest
@@ -15,6 +16,8 @@ class ActivityTypeViewSet(viewsets.ModelViewSet):
     """
     queryset = ActivityType.objects.all()
     serializer_class = ActivityTypeSerializer
+    filter_backends = [DjangoFilterBackend]
+    filterset_fields = ['name', 'can_invite', ]
 
 
 class ActivityViewSet(viewsets.ModelViewSet):
@@ -25,6 +28,8 @@ class ActivityViewSet(viewsets.ModelViewSet):
     """
     queryset = Activity.objects.all()
     serializer_class = ActivitySerializer
+    filter_backends = [DjangoFilterBackend]
+    filterset_fields = ['name', 'description', 'activity_type', ]
 
 
 class GuestViewSet(viewsets.ModelViewSet):
@@ -35,3 +40,5 @@ class GuestViewSet(viewsets.ModelViewSet):
     """
     queryset = Guest.objects.all()
     serializer_class = GuestSerializer
+    filter_backends = [SearchFilter]
+    search_fields = ['$name', ]
diff --git a/apps/api/urls.py b/apps/api/urls.py
index bb1fdce2255a66a53897e874b4b1b7daf0814412..8e0f641514eaf61b9389e133ed07ff6a3647b1df 100644
--- a/apps/api/urls.py
+++ b/apps/api/urls.py
@@ -3,7 +3,9 @@
 
 from django.conf.urls import url, include
 from django.contrib.auth.models import User
+from django_filters.rest_framework import DjangoFilterBackend
 from rest_framework import routers, serializers, viewsets
+from rest_framework.filters import SearchFilter
 from activity.api.urls import register_activity_urls
 from member.api.urls import register_members_urls
 from note.api.urls import register_note_urls
@@ -33,6 +35,9 @@ class UserViewSet(viewsets.ModelViewSet):
     """
     queryset = User.objects.all()
     serializer_class = UserSerializer
+    filter_backends = [DjangoFilterBackend, SearchFilter]
+    filterset_fields = ['id', 'username', 'first_name', 'last_name', 'email', 'is_superuser', 'is_staff', 'is_active', ]
+    search_fields = ['$username', '$first_name', '$last_name', ]
 
 
 # Routers provide an easy way of automatically determining the URL conf.
diff --git a/apps/logs/api/views.py b/apps/logs/api/views.py
index 60da612be41793319d240a617b6eff43f523740a..5b1b3ff60d79233bf0a8f8e2f6016c5b6ddeb23d 100644
--- a/apps/logs/api/views.py
+++ b/apps/logs/api/views.py
@@ -1,6 +1,7 @@
 # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
 # SPDX-License-Identifier: GPL-3.0-or-later
 
+from django_filters.rest_framework import DjangoFilterBackend
 from rest_framework import viewsets
 
 from .serializers import ChangelogSerializer
@@ -15,3 +16,5 @@ class ChangelogViewSet(viewsets.ModelViewSet):
     """
     queryset = Changelog.objects.all()
     serializer_class = ChangelogSerializer
+    filter_backends = [DjangoFilterBackend]
+    filterset_fields = ['model', 'action', "instance_pk", 'user', 'ip',]
diff --git a/apps/logs/signals.py b/apps/logs/signals.py
index 41f87cdab58c45cd996fea2094329d2a75ded26e..ab1962917202a0e978e4e525a7fb4198b7cf12a1 100644
--- a/apps/logs/signals.py
+++ b/apps/logs/signals.py
@@ -81,7 +81,7 @@ def save_object(sender, instance, **kwargs):
             model = instance.__class__
             fields = '__all__'
 
-    previous_json = JSONRenderer().render(CustomSerializer(previous).data).decode("UTF-8")
+    previous_json = JSONRenderer().render(CustomSerializer(previous).data).decode("UTF-8") if previous else None
     instance_json = JSONRenderer().render(CustomSerializer(instance).data).decode("UTF-8")
 
     if previous_json == instance_json:
diff --git a/apps/logs/urls.py b/apps/logs/urls.py
deleted file mode 100644
index 6d76674c0b0835042b4c6ae15d843d29dd070612..0000000000000000000000000000000000000000
--- a/apps/logs/urls.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-app_name = 'logs'
-
-# TODO User interface
-urlpatterns = [
-]
diff --git a/apps/member/api/views.py b/apps/member/api/views.py
index 7e7dcd1d41bed62d91b82e625f750a59845af839..c85df90330ae00463306d30b6bec3da8c22abc97 100644
--- a/apps/member/api/views.py
+++ b/apps/member/api/views.py
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 from rest_framework import viewsets
+from rest_framework.filters import SearchFilter
 
 from .serializers import ProfileSerializer, ClubSerializer, RoleSerializer, MembershipSerializer
 from ..models import Profile, Club, Role, Membership
@@ -25,6 +26,8 @@ class ClubViewSet(viewsets.ModelViewSet):
     """
     queryset = Club.objects.all()
     serializer_class = ClubSerializer
+    filter_backends = [SearchFilter]
+    search_fields = ['$name', ]
 
 
 class RoleViewSet(viewsets.ModelViewSet):
@@ -35,6 +38,8 @@ class RoleViewSet(viewsets.ModelViewSet):
     """
     queryset = Role.objects.all()
     serializer_class = RoleSerializer
+    filter_backends = [SearchFilter]
+    search_fields = ['$name', ]
 
 
 class MembershipViewSet(viewsets.ModelViewSet):
diff --git a/apps/note/api/serializers.py b/apps/note/api/serializers.py
index 61257ec454e635b5e2f8675f28102b57cd6ab3f1..73beead1aa374327e1449e1e6905c293702551ac 100644
--- a/apps/note/api/serializers.py
+++ b/apps/note/api/serializers.py
@@ -5,7 +5,8 @@ from rest_framework import serializers
 from rest_polymorphic.serializers import PolymorphicSerializer
 
 from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
-from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory
+from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory, \
+    TemplateTransaction
 
 
 class NoteSerializer(serializers.ModelSerializer):
@@ -111,6 +112,17 @@ class TransactionSerializer(serializers.ModelSerializer):
         fields = '__all__'
 
 
+class TemplateTransactionSerializer(serializers.ModelSerializer):
+    """
+    REST API Serializer for Transactions.
+    The djangorestframework plugin will analyse the model `TemplateTransaction` and parse all fields in the API.
+    """
+
+    class Meta:
+        model = TemplateTransaction
+        fields = '__all__'
+
+
 class MembershipTransactionSerializer(serializers.ModelSerializer):
     """
     REST API Serializer for Membership transactions.
@@ -120,3 +132,11 @@ class MembershipTransactionSerializer(serializers.ModelSerializer):
     class Meta:
         model = MembershipTransaction
         fields = '__all__'
+
+
+class TransactionPolymorphicSerializer(PolymorphicSerializer):
+    model_serializer_mapping = {
+        Transaction: TransactionSerializer,
+        TemplateTransaction: TemplateTransactionSerializer,
+        MembershipTransaction: MembershipTransactionSerializer,
+    }
diff --git a/apps/note/api/urls.py b/apps/note/api/urls.py
index 5e176ec57c8c46465d130755c6f21f93a7b87721..796a397f746aefd02c2e97b9aaf73bb25454f65a 100644
--- a/apps/note/api/urls.py
+++ b/apps/note/api/urls.py
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 from .views import NotePolymorphicViewSet, AliasViewSet, \
-    TemplateCategoryViewSet, TransactionViewSet, TransactionTemplateViewSet, MembershipTransactionViewSet
+    TemplateCategoryViewSet, TransactionViewSet, TransactionTemplateViewSet
 
 
 def register_note_urls(router, path):
@@ -15,4 +15,3 @@ def register_note_urls(router, path):
     router.register(path + '/transaction/category', TemplateCategoryViewSet)
     router.register(path + '/transaction/transaction', TransactionViewSet)
     router.register(path + '/transaction/template', TransactionTemplateViewSet)
-    router.register(path + '/transaction/membership', MembershipTransactionViewSet)
diff --git a/apps/note/api/views.py b/apps/note/api/views.py
index 4fbb9481503d80f7981f8de376a670a2bd260e92..14f640032f95fca049a4424502755173c8120182 100644
--- a/apps/note/api/views.py
+++ b/apps/note/api/views.py
@@ -2,13 +2,15 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 from django.db.models import Q
+from django_filters.rest_framework import DjangoFilterBackend
 from rest_framework import viewsets
+from rest_framework.filters import SearchFilter
 
 from .serializers import NoteSerializer, NotePolymorphicSerializer, NoteClubSerializer, NoteSpecialSerializer, \
     NoteUserSerializer, AliasSerializer, \
-    TemplateCategorySerializer, TransactionTemplateSerializer, TransactionSerializer, MembershipTransactionSerializer
+    TemplateCategorySerializer, TransactionTemplateSerializer, TransactionPolymorphicSerializer
 from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
-from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory
+from ..models.transactions import TransactionTemplate, Transaction, TemplateCategory
 
 
 class NoteViewSet(viewsets.ModelViewSet):
@@ -139,6 +141,8 @@ class TemplateCategoryViewSet(viewsets.ModelViewSet):
     """
     queryset = TemplateCategory.objects.all()
     serializer_class = TemplateCategorySerializer
+    filter_backends = [SearchFilter]
+    search_fields = ['$name', ]
 
 
 class TransactionTemplateViewSet(viewsets.ModelViewSet):
@@ -149,6 +153,8 @@ class TransactionTemplateViewSet(viewsets.ModelViewSet):
     """
     queryset = TransactionTemplate.objects.all()
     serializer_class = TransactionTemplateSerializer
+    filter_backends = [DjangoFilterBackend]
+    filterset_fields = ['name', 'amount', 'display', 'category', ]
 
 
 class TransactionViewSet(viewsets.ModelViewSet):
@@ -158,14 +164,6 @@ class TransactionViewSet(viewsets.ModelViewSet):
     then render it on /api/note/transaction/transaction/
     """
     queryset = Transaction.objects.all()
-    serializer_class = TransactionSerializer
-
-
-class MembershipTransactionViewSet(viewsets.ModelViewSet):
-    """
-    REST API View set.
-    The djangorestframework plugin will get all `MembershipTransaction` objects, serialize it to JSON with the given serializer,
-    then render it on /api/note/transaction/membership/
-    """
-    queryset = MembershipTransaction.objects.all()
-    serializer_class = MembershipTransactionSerializer
+    serializer_class = TransactionPolymorphicSerializer
+    filter_backends = [SearchFilter]
+    search_fields = ['$reason', ]
diff --git a/apps/note/fixtures/initial.json b/apps/note/fixtures/initial.json
index 01242b2201110f403fdf86d8a7b54ba5de2413f3..3654fa2f5f24c17498de4452295d1a899d798f1b 100644
--- a/apps/note/fixtures/initial.json
+++ b/apps/note/fixtures/initial.json
@@ -3,7 +3,7 @@
         "model": "note.note",
         "pk": 1,
         "fields": {
-            "polymorphic_ctype": 37,
+            "polymorphic_ctype": 40,
             "balance": 0,
             "is_active": true,
             "display_image": "",
@@ -14,7 +14,7 @@
         "model": "note.note",
         "pk": 2,
         "fields": {
-            "polymorphic_ctype": 37,
+            "polymorphic_ctype": 40,
             "balance": 0,
             "is_active": true,
             "display_image": "",
@@ -25,7 +25,7 @@
         "model": "note.note",
         "pk": 3,
         "fields": {
-            "polymorphic_ctype": 37,
+            "polymorphic_ctype": 40,
             "balance": 0,
             "is_active": true,
             "display_image": "",
@@ -36,7 +36,7 @@
         "model": "note.note",
         "pk": 4,
         "fields": {
-            "polymorphic_ctype": 37,
+            "polymorphic_ctype": 40,
             "balance": 0,
             "is_active": true,
             "display_image": "",
@@ -47,7 +47,7 @@
         "model": "note.note",
         "pk": 5,
         "fields": {
-            "polymorphic_ctype": 36,
+            "polymorphic_ctype": 39,
             "balance": 0,
             "is_active": true,
             "display_image": "",
@@ -58,7 +58,7 @@
         "model": "note.note",
         "pk": 6,
         "fields": {
-            "polymorphic_ctype": 36,
+            "polymorphic_ctype": 39,
             "balance": 0,
             "is_active": true,
             "display_image": "",
diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py
index 84f07b6cbb828df762a2b9a5474b6392432d5bd4..0694390d778e3b65f33bfe3c191251bb844bb87e 100644
--- a/note_kfet/settings/base.py
+++ b/note_kfet/settings/base.py
@@ -137,12 +137,14 @@ REST_FRAMEWORK = {
     # or allow read-only access for unauthenticated users.
     'DEFAULT_PERMISSION_CLASSES': [
         # TODO Maybe replace it with our custom permissions system
-        'rest_framework.permissions.DjangoModelPermissions'
+        'rest_framework.permissions.DjangoModelPermissions',
     ],
     'DEFAULT_AUTHENTICATION_CLASSES': [
         'rest_framework.authentication.SessionAuthentication',
         'rest_framework.authentication.TokenAuthentication',
-    ]
+    ],
+    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
+    'PAGE_SIZE': 20,
 }
 
 # Internationalization
diff --git a/note_kfet/urls.py b/note_kfet/urls.py
index 407659f8e6eaf39f8ce60afdcd856256ae1013ed..da2f9d6c246833c3962b8b0727869a9585b5c4f9 100644
--- a/note_kfet/urls.py
+++ b/note_kfet/urls.py
@@ -20,8 +20,7 @@ urlpatterns = [
     path('accounts/', include('django.contrib.auth.urls')),
     path('admin/doc/', include('django.contrib.admindocs.urls')),
     path('admin/', admin.site.urls),
-    path('logs/', include('logs.urls')),
-    path('api/', include('api.urls')),  
+    path('api/', include('api.urls')),
 ]
 
 urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/templates/django_filters/rest_framework/crispy_form.html b/templates/django_filters/rest_framework/crispy_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..171767c086cc5fe7f96816d6b0a2c2bfc50b1d08
--- /dev/null
+++ b/templates/django_filters/rest_framework/crispy_form.html
@@ -0,0 +1,5 @@
+{% load crispy_forms_tags %}
+{% load i18n %}
+
+<h2>{% trans "Field filters" %}</h2>
+{% crispy filter.form %}
diff --git a/templates/django_filters/rest_framework/form.html b/templates/django_filters/rest_framework/form.html
new file mode 100644
index 0000000000000000000000000000000000000000..b116e35317537ecf43046b79a4ca7525d1dc80c0
--- /dev/null
+++ b/templates/django_filters/rest_framework/form.html
@@ -0,0 +1,6 @@
+{% load i18n %}
+<h2>{% trans "Field filters" %}</h2>
+<form class="form" action="" method="get">
+    {{ filter.form.as_p }}
+    <button type="submit" class="btn btn-primary">{% trans "Submit" %}</button>
+</form>
diff --git a/templates/django_filters/widgets/multiwidget.html b/templates/django_filters/widgets/multiwidget.html
new file mode 100644
index 0000000000000000000000000000000000000000..089ddb20c9fccebb7562d4cb0c400ba0a6f3020c
--- /dev/null
+++ b/templates/django_filters/widgets/multiwidget.html
@@ -0,0 +1 @@
+{% for widget in widget.subwidgets %}{% include widget.template_name %}{% if forloop.first %}-{% endif %}{% endfor %}