diff --git a/events.py b/events.py
index 3b7c15a4f00f9ab964e6f79bc99548953d7409fb..2e1963458890d2c31cc5bbfde9d044576c3d296e 100644
--- a/events.py
+++ b/events.py
@@ -10,6 +10,11 @@ def get_event_type(cloud_event: CloudEvent) -> str:
 def get_event_version(cloud_event: CloudEvent) -> str:
     return cloud_event.data['message']['attributes']['eventVersion']
 
+def _validate_event_type(cloud_event: CloudEvent, expected_event_type: str) -> None:
+    event_type = get_event_type(cloud_event)
+    if event_type != expected_event_type:
+        raise ValueError(f'Expected event of type {expected_event_type}, got {event_type}')
+
 @dataclass
 class UserPayload:
     id: str
@@ -43,13 +48,55 @@ class UserEvent:
 @dataclass
 class UserNameUpdatedEvent(UserEvent):
     def __init__(self, cloud_event: CloudEvent):
-        if get_event_type(cloud_event) != 'UserNameUpdated':
-            raise ValueError(f'Expected event of type UserNameUpdated, got {data['eventType']}')
+        _validate_event_type(cloud_event, 'UserNameUpdated')
         super().__init__(cloud_event)
 
 @dataclass
 class UserDeletedEvent(UserEvent):
     def __init__(self, cloud_event: CloudEvent):
-        if get_event_type(cloud_event) != 'UserDeleted':
-            raise ValueError(f'Expected event of type UserDeleted, got {data['eventType']}')
+        _validate_event_type(cloud_event, 'UserDeleted')
         super().__init__(cloud_event)
+
+@dataclass
+class SpacePayload:
+    id: str
+    name: str
+    slug: str
+    avatar: str
+    avatar_default_color: str
+
+    def __init__(self, data: dict):
+        self.id = data['space']['id']
+        self.name = data['space']['name']
+        self.slug = data['space']['slug']
+        self.avatar = data['space']['avatar']
+        self.avatar_default_color = data['space']['avatarDefaultColor']
+
+@dataclass
+class SpaceEvent:
+    event_type: str
+    event_version: str
+    space: SpacePayload
+
+    def __init__(self, cloud_event: CloudEvent):
+        self.event_type = get_event_type(cloud_event)
+        self.event_version = get_event_version(cloud_event)
+        self.space = SpacePayload(json.loads(base64.b64decode(cloud_event.data['message']['data'])))
+
+@dataclass
+class SpaceCreatedEvent(SpaceEvent):
+    def __init__(self, cloud_event: CloudEvent):
+        _validate_event_type(cloud_event, 'SpaceCreated')
+        super().__init__(cloud_event)
+
+@dataclass
+class SpaceUpdatedEvent(SpaceEvent):
+    def __init__(self, cloud_event: CloudEvent):
+        _validate_event_type(cloud_event, 'SpaceUpdated')
+        super().__init__(cloud_event)
+
+@dataclass
+class SpaceDeletedEvent(SpaceEvent):
+    def __init__(self, cloud_event: CloudEvent):
+        _validate_event_type(cloud_event, 'SpaceDeleted')
+        super().__init__(cloud_event)
\ No newline at end of file
diff --git a/main.py b/main.py
index d828827008b80f7088bd069a5761acdb54d48639..ad19fc6a0909a66d2aaaf51940db77493d75dd29 100644
--- a/main.py
+++ b/main.py
@@ -1,10 +1,12 @@
 import os
 import functions_framework
+from typing import Union
 
 from dataclasses import asdict
 from cloudevents.http.event import CloudEvent
 
-from events import UserNameUpdatedEvent, get_event_type, get_event_version, UserDeletedEvent
+from events import UserNameUpdatedEvent, get_event_type, get_event_version, UserDeletedEvent, SpaceCreatedEvent, \
+    SpaceUpdatedEvent, SpaceDeletedEvent
 from typesense_client import TypesenseClient
 
 from logging import getLogger
@@ -28,13 +30,37 @@ def process_user_name_updated_event(client: TypesenseClient, event: UserNameUpda
         }
     }
     client.upsert(document)
-    logger.info(f'Updated user {event.user.id} in Typesense')
+    logger.info(f'Upserted user {event.user.id} in Typesense')
 
 def process_user_deleted_event(client: TypesenseClient, event: UserDeletedEvent):
     logger.debug(f'Processing {event}')
     client.delete(f"profile_{event.user.id}")
     logger.info(f'Deleted user {event.user.id} from Typesense')
 
+def process_space_upserting_event(client: TypesenseClient, event: Union[SpaceCreatedEvent, SpaceUpdatedEvent]):
+    logger.debug(f'Processing {event}')
+    document = {
+        'id': f'space_{event.space.id}',
+        'type': 'space',
+        'title_de': event.space.name,
+        'title_en': event.space.name,
+        'description_de': None,  # TODO add on sending side
+        'description_en': None,  # TODO add on sending side
+        'location': None,
+        'location_lat_lng': None,
+        'image_url': event.space.avatar,
+        'link_locators': {
+            'space': event.space.slug
+        }
+    }
+    client.upsert(document)
+    logger.info(f'Upserted space {event.space.id} in Typesense')
+
+def process_space_deleted_event(client: TypesenseClient, event: SpaceDeletedEvent):
+    logger.debug(f'Processing {event}')
+    client.delete(f"space_{event.space.id}")
+    logger.info(f'Deleted space {event.space.id} in Typesense')
+
 def process_event(client: TypesenseClient, event: CloudEvent):
     type_version = (get_event_type(event), get_event_version(event))
     match type_version:
@@ -47,16 +73,13 @@ def process_event(client: TypesenseClient, event: CloudEvent):
             logger.debug('Ignoring UserEmailUpdated event')
             pass
         case ('SpaceCreated', '1.0.0'):
-            # TODO implement
-            logger.debug('Ignoring SpaceCreated event (yet to be implemented)')
+            process_space_upserting_event(client, SpaceCreatedEvent(event))
             pass
         case ('SpaceUpdated', '1.0.0'):
-            # TODO implement
-            logger.debug('Ignoring SpaceCreated event (yet to be implemented)')
+            process_space_upserting_event(client, SpaceUpdatedEvent(event))
             pass
         case ('SpaceDeleted', '1.0.0'):
-            # TODO implement
-            logger.debug('Ignoring SpaceCreated event (yet to be implemented)')
+            process_space_deleted_event(client, SpaceDeletedEvent(event))
             pass
         case (eventType, eventVersion):
             logger.debug(f'Ignoring {eventType} ({eventVersion}) event.')
diff --git a/test_main.py b/test_main.py
index a5acd3d1a81990968d8255a10067107b788b3966..5ec5729b44cc735f7552c7d22f1b6e50bb669880 100644
--- a/test_main.py
+++ b/test_main.py
@@ -1,10 +1,10 @@
 import base64
 import json
-
 from unittest.mock import patch
 
-from cloudevents.http import CloudEvent
+# noinspection PyPackageRequirements
 from cloudevents.http.event import CloudEvent
+
 from main import process_event
 
 attributes = {
@@ -24,6 +24,14 @@ user_payload = {
     'avatar': 'https://ik.imagekit.io/holi/_DEV_/avatar/149a3d29-a0da-4f52-8e1c-660376b7084b_yv31UW7lD0.jpg',
 }
 
+space_payload = {
+    'id': '149a3d29-a0da-4f52-8e1c-660376b7084b',
+    'name': 'Daniels Space',
+    'slug': 'daniels-space',
+    'avatar': 'https://ik.imagekit.io/holi/_DEV_/avatar/149a3d29-a0da-4f52-8e1c-660376b7084b_yv31UW7lD0.jpg',
+    'avatarDefaultColor': 'ffffff',
+}
+
 def message_data(event_type, event_version, data):
     return {
         'message': {
@@ -46,10 +54,10 @@ def test_user_name_updated(mock_client):
         'type': 'profile',
         'title_de': user_payload['name'],
         'title_en': user_payload['name'],
-        'description_de': None,  # TODO add on sending side
-        'description_en': None,  # TODO add on sending side
-        'location': None,  # TODO add on sending side
-        'location_lat_lng': None,  # TODO add on sending side
+        'description_de': None,
+        'description_en': None,
+        'location': None,
+        'location_lat_lng': None,
         'image_url': user_payload['avatar'],
         'link_locators': {
             'profile': user_payload['id'],
@@ -61,5 +69,40 @@ def test_user_deleted(mock_client):
     process_event(mock_client, CloudEvent(attributes, message_data('UserDeleted', '1.0.0', {'user': user_payload})))
     mock_client.delete.assert_called_with(f"profile_{user_payload['id']}")
 
-if __name__ == '__main__':
-    process_event()
\ No newline at end of file
+# noinspection DuplicatedCode
+@patch('typesense.client.Client')
+def test_space_created(mock_client):
+    process_event(mock_client, CloudEvent(attributes, message_data('SpaceCreated', '1.0.0', {'space': space_payload})))
+    mock_client.upsert.assert_called_with({
+        'id': f'space_{space_payload['id']}',
+        'type': 'space',
+        'title_de': space_payload['name'],
+        'title_en': space_payload['name'],
+        'description_de': None,
+        'description_en': None,
+        'location': None,
+        'location_lat_lng': None,
+        'image_url': space_payload['avatar'],
+        'link_locators': {
+            'space': space_payload['slug'],
+        }
+    })
+
+# noinspection DuplicatedCode
+@patch('typesense.client.Client')
+def test_space_updated(mock_client):
+    process_event(mock_client, CloudEvent(attributes, message_data('SpaceUpdated', '1.0.0', {'space': space_payload})))
+    mock_client.upsert.assert_called_with({
+        'id': f'space_{space_payload['id']}',
+        'type': 'space',
+        'title_de': space_payload['name'],
+        'title_en': space_payload['name'],
+        'description_de': None,
+        'description_en': None,
+        'location': None,
+        'location_lat_lng': None,
+        'image_url': space_payload['avatar'],
+        'link_locators': {
+            'space': space_payload['slug'],
+        }
+    })