diff --git a/api/funkwhale_api/favorites/activities.py b/api/funkwhale_api/favorites/activities.py
new file mode 100644
index 0000000000000000000000000000000000000000..a9deef552586c0cc210dcf0745d224f90c42e6a8
--- /dev/null
+++ b/api/funkwhale_api/favorites/activities.py
@@ -0,0 +1,17 @@
+from funkwhale_api.common import channels
+from funkwhale_api.activity import record
+
+from . import serializers
+
+record.registry.register_serializer(
+    serializers.TrackFavoriteActivitySerializer)
+
+
+@record.registry.register_consumer('favorites.TrackFavorite')
+def broadcast_track_favorite_to_instance_timeline(data, obj):
+    if obj.user.privacy_level not in ['instance', 'everyone']:
+        return
+    channels.group_send('instance_timeline', {
+        'type': 'event',
+        'data': data
+    })
diff --git a/api/funkwhale_api/favorites/consumers.py b/api/funkwhale_api/favorites/consumers.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/api/funkwhale_api/favorites/views.py b/api/funkwhale_api/favorites/views.py
index 08ae00b684c30bcf5df91d5438dae1c03c790259..d874c9e1e626b9b30101088217336735d544a0e1 100644
--- a/api/funkwhale_api/favorites/views.py
+++ b/api/funkwhale_api/favorites/views.py
@@ -4,6 +4,7 @@ from rest_framework.response import Response
 from rest_framework import pagination
 from rest_framework.decorators import list_route
 
+from funkwhale_api.activity import record
 from funkwhale_api.music.models import Track
 from funkwhale_api.common.permissions import ConditionalAuthentication
 
@@ -33,6 +34,7 @@ class TrackFavoriteViewSet(mixins.CreateModelMixin,
         instance = self.perform_create(serializer)
         serializer = self.get_serializer(instance=instance)
         headers = self.get_success_headers(serializer.data)
+        record.send(instance)
         return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
 
     def get_queryset(self):
diff --git a/api/tests/favorites/test_activity.py b/api/tests/favorites/test_activity.py
index b4d76658a8688fd4dc81144e288653186b18e1c2..84778fd0fc8779ca1bf32ddfa8e69621ad6fa492 100644
--- a/api/tests/favorites/test_activity.py
+++ b/api/tests/favorites/test_activity.py
@@ -1,5 +1,6 @@
 from funkwhale_api.users.serializers import UserActivitySerializer
 from funkwhale_api.favorites import serializers
+from funkwhale_api.favorites import activities
 
 
 def test_get_favorite_activity_url(settings, factories):
@@ -26,3 +27,45 @@ def test_activity_favorite_serializer(factories):
     data = serializers.TrackFavoriteActivitySerializer(favorite).data
 
     assert data == expected
+
+
+def test_track_favorite_serializer_is_connected(activity_registry):
+    conf = activity_registry['favorites.TrackFavorite']
+    assert conf['serializer'] == serializers.TrackFavoriteActivitySerializer
+
+
+def test_track_favorite_serializer_instance_activity_consumer(
+        activity_registry):
+    conf = activity_registry['favorites.TrackFavorite']
+    consumer = activities.broadcast_track_favorite_to_instance_timeline
+    assert consumer in conf['consumers']
+
+
+def test_broadcast_track_favorite_to_instance_timeline(
+        factories, mocker):
+    p = mocker.patch('funkwhale_api.common.channels.group_send')
+    favorite = factories['favorites.TrackFavorite']()
+    data = serializers.TrackFavoriteActivitySerializer(favorite).data
+    consumer = activities.broadcast_track_favorite_to_instance_timeline
+    message = {
+        "type": 'event',
+        "data": data
+    }
+    consumer(data=data, obj=favorite)
+    p.assert_called_once_with('instance_timeline', message)
+
+
+def test_broadcast_track_favorite_to_instance_timeline_private(
+        factories, mocker):
+    p = mocker.patch('funkwhale_api.common.channels.group_send')
+    favorite = factories['favorites.TrackFavorite'](
+        user__privacy_level='me'
+    )
+    data = serializers.TrackFavoriteActivitySerializer(favorite).data
+    consumer = activities.broadcast_track_favorite_to_instance_timeline
+    message = {
+        "type": 'event',
+        "data": data
+    }
+    consumer(data=data, obj=favorite)
+    p.assert_not_called()
diff --git a/api/tests/favorites/test_favorites.py b/api/tests/favorites/test_favorites.py
index 8165722eacc969a9ea651dd70815d3fa1d9c75ea..f4a045af825e9431f308903569ac16b07d609692 100644
--- a/api/tests/favorites/test_favorites.py
+++ b/api/tests/favorites/test_favorites.py
@@ -33,7 +33,8 @@ def test_user_can_get_his_favorites(factories, logged_in_client, client):
     assert expected == parsed_json['results']
 
 
-def test_user_can_add_favorite_via_api(factories, logged_in_client, client):
+def test_user_can_add_favorite_via_api(
+        factories, logged_in_client, activity_muted):
     track = factories['music.Track']()
     url = reverse('api:v1:favorites:tracks-list')
     response = logged_in_client.post(url, {'track': track.pk})
@@ -51,6 +52,27 @@ def test_user_can_add_favorite_via_api(factories, logged_in_client, client):
     assert favorite.user == logged_in_client.user
 
 
+def test_adding_favorites_calls_activity_record(
+        factories, logged_in_client, activity_muted):
+    track = factories['music.Track']()
+    url = reverse('api:v1:favorites:tracks-list')
+    response = logged_in_client.post(url, {'track': track.pk})
+
+    favorite = TrackFavorite.objects.latest('id')
+    expected = {
+        'track': track.pk,
+        'id': favorite.id,
+        'creation_date': favorite.creation_date.isoformat().replace('+00:00', 'Z'),
+    }
+    parsed_json = json.loads(response.content.decode('utf-8'))
+
+    assert expected == parsed_json
+    assert favorite.track == track
+    assert favorite.user == logged_in_client.user
+
+    activity_muted.assert_called_once_with(favorite)
+
+
 def test_user_can_remove_favorite_via_api(logged_in_client, factories, client):
     favorite = factories['favorites.TrackFavorite'](user=logged_in_client.user)
     url = reverse('api:v1:favorites:tracks-detail', kwargs={'pk': favorite.pk})