diff --git a/src/api/tests/schedule.py b/src/api/tests/schedule.py
index 66424c5ac2f90ebdfe2f302149aab75b4afd7374..ea04dd5f52853a99f4cc718ee3d7c3a9eaed197e 100644
--- a/src/api/tests/schedule.py
+++ b/src/api/tests/schedule.py
@@ -65,6 +65,9 @@ class ScheduleTest(TestCase):
         self.assertIsNotNone(event.schedule_end)
 
     def test_push_new_event(self):
+        another_room = Room(conference=self.conf, assembly=self.assembly, room_type=Room.RoomType.STAGE)
+        another_room.save()
+
         update = {
             "url": "https://fahrplan.events.ccc.de/rc3/2020/Fahrplan/events/11583.html",
             "id": 11583,
@@ -74,6 +77,7 @@ class ScheduleTest(TestCase):
             "start": "12:20",
             "duration": "01:30",
             "room": "foo room",
+            "room_id": str(another_room.pk),
             "slug": "rc3-11583-rc3_eroffnung",
             "title": "#rC3 Er\u00f6ffnung",
             "subtitle": "",
@@ -103,3 +107,5 @@ class ScheduleTest(TestCase):
         self.assertTrue('rC3' in event.name, f'Expected "rC3" in event name "{event.name}".')
         self.assertEqual(timedelta(minutes=90), event.schedule_duration)
         self.assertIsNotNone(event.schedule_end)
+
+        self.assertEqual(another_room.pk, event.room_id, 'Expected import to prefer "room_id" over "room".')
diff --git a/src/api/views/schedule.py b/src/api/views/schedule.py
index 65ecbcd9b25f0001b9c668be47195fb44e0d2b33..c3d495c270201b6a4d38648fd1cae3843d0e15d7 100644
--- a/src/api/views/schedule.py
+++ b/src/api/views/schedule.py
@@ -10,6 +10,7 @@ from rest_framework.response import Response
 from rest_framework.views import APIView
 import pytz
 
+from core.models.assemblies import Assembly
 from core.models.events import Event
 from core.models.rooms import Room
 from core.models.conference import ConferenceTrack
@@ -97,39 +98,65 @@ class EventSchedule(ConferenceSlugMixin, APIView):
             logger.warning('Event schedule POST: id %s did not exist yet, creating.', pk)
 
         try:
-            if 'guid' in event:
-                if event['guid'] != str(obj.pk):
-                    logger.warning('Attempted update of event %s with guid "%s".', obj.pk, event["guid"])
-                    return JsonResponse({'error': 'GUID mismatch.'})
+            if (event_guid := event.get('guid')) is not None:
+                if event_guid != str(obj.pk):
+                    logger.warning('Attempted update of event %s with guid "%s".', obj.pk, event_guid)
+                    return JsonResponse({'error': 'GUID mismatch.'}, status=400)
 
-            if 'slug' in event:
-                obj.slug = event['slug']
+            if (event_slug := event.get('slug')) is not None:
+                obj.slug = event_slug
+
+            if (event_roomid := event.get('room_id')) is not None:
+                obj.room = Room.objects.get(conference=self.conference, pk=event_roomid)
+
+            elif (event_room := event.get('room')) is not None:
+                try:
+                    obj.room = Room.objects.get(conference=self.conference, name__iexact=event_room)
+                except Room.MultipleObjectsReturned:
+                    return JsonResponse({'error': 'Room name is not unique, please provide room_id!'}, status=400)
+
+            if (event_assemblyid := event.get('assembly_id')) is not None:
+                obj.assembly = Assembly.objects.get(conference=self.conference, pk=event_assemblyid)
+
+            elif (event_assemblyslug := event.get('assembly_slug')) is not None:
+                obj.assembly = Assembly.objects.get(conference=self.conference, slug__iexact=event_assemblyslug)
+
+            if obj.assembly_id is None:
+                if obj.room_id is not None:
+                    obj.assembly = obj.room.assembly
+                else:
+                    return JsonResponse({'error': 'Assembly association missing, please provide assembly_id or a valid room.'}, status=400)
 
-            obj.room = Room.objects.get(conference=self.conference, name__iexact=event['room'])
-            obj.assembly = obj.room.assembly
             obj.kind = 'assembly' if not obj.room.assembly.is_official else 'official'
             obj.is_public = True
 
-            if 'title' in event:
-                obj.name = event['title']
+            if (event_title := event.get('title')) is not None:
+                obj.name = event_title
 
-            if 'language' in event:
-                obj.language = event['language']
+            if (event_language := event.get('language')) is not None:
+                obj.language = event_language
 
-            obj.description = str(event['abstract']) + "\n\n" + str(event['description'])
+            if (event_abstract := event.get('abstract')) is not None and (event_description := event.get('description')) is not None:
+                obj.description = str(event_abstract) + '\n\n' + str(event_description)
 
-            obj.schedule_start = parse_datetime(event['date'])
-            obj.schedule_duration = schedulexml_time_to_timedelta(event['duration'])
+            if (event_date := event.get('date')) is not None:
+                obj.schedule_start = parse_datetime(event_date)
+            if (event_duration := event.get('duration')) is not None:
+                obj.schedule_duration = schedulexml_time_to_timedelta(event_duration)
 
-            obj.track = ConferenceTrack.objects.get(conference=self.conference, name__iexact=event['track'])
+            if (event_track := event.get('track')) is not None:
+                obj.track = ConferenceTrack.objects.get(conference=self.conference, name__iexact=event_track)
 
             obj.additional_data = filter_additional_data(event)
 
+        except Assembly.DoesNotExist:
+            return Response({'error': f'Assembly {event.get("assembly_id")}/{event.get("assembly_slug")} does not exist.'}, status=400)
+
         except Room.DoesNotExist:
-            return Response({'error': 'Room {} does not exist'.format(event['room'])}, status=400)
+            return Response({'error': f'Room {event.get("room_id")}/{event.get("room")} does not exist.'}, status=400)
 
         except ConferenceTrack.DoesNotExist:
-            return Response({'error': 'Track {} does not exist'.format(event['track'])}, status=400)
+            return Response({'error': f'Track {event.get("track_id")}/{event.get("track")} does not exist.'}, status=400)
 
         obj.save()
         logger.info('Event %s updated via POST by %s', obj, request.user)