diff --git a/src/api/serializers.py b/src/api/serializers.py
index e0a344ae4a481f727e1d5d525ca9f6a29684a07f..fc125a402c9c11d813e979c6c27732fd6430bbb5 100644
--- a/src/api/serializers.py
+++ b/src/api/serializers.py
@@ -11,6 +11,7 @@ from core.models.assemblies import Assembly
 from core.models.badges import Badge, BadgeToken, BadgeTokenTimeConstraint
 from core.models.conference import Conference, ConferenceMember, ConferenceTrack
 from core.models.events import Event
+from core.models.links import Link
 from core.models.messages import DirectMessage
 from core.models.metanavi import MetaNavItem
 from core.models.rooms import Room
@@ -50,6 +51,20 @@ class ParameterisedHyperlinkedIdentityField(HyperlinkedIdentityField):
         return reverse(view_name, kwargs=kwargs, request=request, format=format)
 
 
+class LinkRelatedField(serializers.RelatedField):
+    """
+    A read only field that represents its targets using their
+    plain string representation.
+    """
+
+    def __init__(self, **kwargs):
+        kwargs['read_only'] = True
+        super().__init__(**kwargs)
+
+    def to_representation(self, value: Link):
+        return value.to_dict()
+
+
 class ValidatingModelSerializer(serializers.ModelSerializer):
     def validate(self, data):
         instance = self.Meta.model(**{field: value for field, value in data.items() if field in self.Meta.model._meta.fields})
@@ -217,7 +232,7 @@ class BadgeTokenUpdateSerializer(BadgeTokenSerializer):
 class RoomSerializer(HubModelSerializer):
     assembly = serializers.SlugRelatedField(read_only=True, slug_field='slug')
 
-    links = serializers.StringRelatedField(
+    links = LinkRelatedField(
         many=True,
         read_only=True,
     )
@@ -228,6 +243,7 @@ class RoomSerializer(HubModelSerializer):
         fields = [
             'id',
             'name',
+            'slug',
             'blocked',
             'room_type',
             'capacity',
diff --git a/src/core/models/links.py b/src/core/models/links.py
index 86764e7e409e67adef65819949d2b20d5600766f..b349a28fe9e7688104f4af556f6c63ffd6f35239 100644
--- a/src/core/models/links.py
+++ b/src/core/models/links.py
@@ -62,6 +62,14 @@ class Link(models.Model):
             except ValidationError:
                 raise ValidationError({'link': _('Link__link__must_be_url')})
 
+    def to_dict(self):
+        return {
+            'type': self.link_type,
+            'name': self.name,
+            'uri': self.link,
+            'url': self.link,
+        }
+
     def __str__(self) -> str:
         return self.name
 
diff --git a/src/core/models/rooms.py b/src/core/models/rooms.py
index b54819c259eb740fe27d5810a9ede9ef16a73cac..f614d7ee2e87a7a3555b88ea4d89730321456a4a 100644
--- a/src/core/models/rooms.py
+++ b/src/core/models/rooms.py
@@ -501,5 +501,13 @@ class RoomLink(models.Model):
             if not resolve_internal_url(self.link, fallback_as_is=False):
                 raise ValidationError({'link': _('RoomLink__link__must_be_url')})
 
+    def to_dict(self):
+        return {
+            'type': self.link_type,
+            'name': self.name,
+            'uri': self.link,
+            'url': self.link,  # TODO rendered URL without local hub specific prefixes
+        }
+
     def __str__(self):
         return self.name