diff --git a/src/backoffice/locale/en/LC_MESSAGES/django.po b/src/backoffice/locale/en/LC_MESSAGES/django.po
index 750a6417b354d2be5a65f13c32b07b266e130182..3c2f31a824dc320d3d2e529b36b8629ab0ed1f59 100644
--- a/src/backoffice/locale/en/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/en/LC_MESSAGES/django.po
@@ -1589,7 +1589,7 @@ msgid "TeamMember__actions"
 msgstr "Actions"
 
 msgid "TeamMember__demote_button"
-msgstr "Remote management rights"
+msgstr "Remove management rights"
 
 msgid "TeamMember__promote_button"
 msgstr "Add management rights"
diff --git a/src/backoffice/templates/backoffice/schedule_source_import-detail.html b/src/backoffice/templates/backoffice/schedule_source_import-detail.html
index ec3be03022ad3a310bf8c4ac15812b7502b0a77a..72d72c70c46e5ffbce09898d389c6ac3e48e665e 100644
--- a/src/backoffice/templates/backoffice/schedule_source_import-detail.html
+++ b/src/backoffice/templates/backoffice/schedule_source_import-detail.html
@@ -3,13 +3,18 @@
 {% load i18n %}
 
 {% block content %}
+  <div class="float-end">
+    <form action="{% url 'backoffice:schedulesource-import' pk=object.schedule_source.id %}"
+          method="post">
+      {% csrf_token %}
+      <button type="submit" class="btn btn-outline-primary">re-run import</button>
+    </form>
 
-  {% if object.data %}
-    <div class="float-end">
+    {% if object.data %}
       <a href="{% url 'backoffice:schedulesourceimport-detail-data' pk=object.pk %}"
          class="btn btn-outline-primary">data as JSON</a>
-    </div>
-  {% endif %}
+    {% endif %}
+  </div>
 
   <h1>
     ScheduleSourceImport for "<span title="{{ object.schedule_source.assembly.name }}">{{ object.schedule_source.assembly.slug }}</span>"
@@ -28,9 +33,7 @@
         State: <strong class="{{ object.text_color_class }}">{{ object.state }}</strong>
       </p>
       <p>
-        Summary:
-        <br />
-        <strong>{{ object.summary|linebreaks }}</strong>
+        Summary: <strong>{{ object.summary|linebreaksbr }}</strong>
       </p>
       <p>
         Start: <strong title="{{ object.start }}">{{ object.start|naturaltime }}</strong>
diff --git a/src/backoffice/views/schedules.py b/src/backoffice/views/schedules.py
index b4ffa0b2311124f5867551824970ba9f418c9986..b69c8792f9e4a24eac7fef4d0fb9dabf22c89f91 100644
--- a/src/backoffice/views/schedules.py
+++ b/src/backoffice/views/schedules.py
@@ -128,7 +128,7 @@ class ScheduleSourceImportDetailView(ScheduleAdminMixin, DetailView):
         if data := ctx['object'].data:
             ctx['activity'] = sorted(
                 data.get('_activity', []),
-                key=lambda item: (action2sort.get(item['action'], 99), type2sort.get(item['type'], 99), item['source_id']),
+                key=lambda item: (action2sort.get(item['action'], 99), type2sort.get(item['type'], 99), str(item['source_id'])),
             )
         else:
             ctx['activity'] = None
diff --git a/src/core/models/events.py b/src/core/models/events.py
index 9908758a1ed23a87fc590d33507e0eac0284204f..12e855e0e3cf13154b95f72f14fa03623edce845 100644
--- a/src/core/models/events.py
+++ b/src/core/models/events.py
@@ -483,8 +483,9 @@ class Event(TaggedItemMixin, BackendMixin, ActivityLogMixin, models.Model):
         sos = self.kind == self.Kind.SELF_ORGANIZED
         event_type = _('SoS') if sos else _('event')
 
-        if Event.objects.exclude(id=self.id).filter(conference=self.conference, assembly=self.assembly, name=self.name).exists():
-            errors['name'] = ValidationError(_('Event__name__already_exists %(event_type)s') % {'event_type': event_type}, code='duplicate')
+        if settings.BLOCK_DUPLICATE_EVENT_NAMES:
+            if Event.objects.exclude(id=self.id).filter(conference=self.conference, assembly=self.assembly, name=self.name).exists():
+                errors['name'] = ValidationError(_('Event__name__already_exists %(event_type)s') % {'event_type': event_type}, code='duplicate')
 
         # SoS assembly setting on conference must be set
         if self.assembly and self.conference and sos:
diff --git a/src/core/models/schedules.py b/src/core/models/schedules.py
index 6ef85f09bb2e1221cc50dba818a075998acc892d..d39c6087e179e5e1e983e23188b5a5f3585d6d22 100644
--- a/src/core/models/schedules.py
+++ b/src/core/models/schedules.py
@@ -165,9 +165,9 @@ class ScheduleSource(models.Model):
             raise ValueError('Multiple candidate speakers found: ' + '; '.join(str(x.pk) for x in candidates))
 
         # hail mary attempt: see if we have an imported speaker with the same name
-        candidates = self.conference.users.select_related('user').filter(user__user_type=PlatformUser.Type.SPEAKER, user__display_name=name).all()
-        if len(candidates) == 1:
-            return candidates[0], False
+        # candidates = self.conference.users.select_related('user').filter(user__user_type=PlatformUser.Type.SPEAKER, user__display_name=name).all()
+        # if len(candidates) == 1:
+        #    return candidates[0].user, False
 
         # the expected case: nothing found, create a new one
         name_split = name.split(' ')
@@ -206,51 +206,56 @@ class ScheduleSource(models.Model):
             return mapping, False
 
         except ObjectDoesNotExist:
-            lo = None
-            if create_local_object:
-                if mapping_type == ScheduleSourceMapping.MappingType.ROOM:
-                    try:
-                        if source_uuid:
-                            lo = Room.objects.get(conference=self.conference, pk=source_uuid)
-                        elif self.assembly:
-                            lo = Room.objects.get(conference=self.conference, assembly=self.assembly, name__iexact=source_id)
-                        else:
-                            lo = Room.objects.get(conference=self.conference, name__iexact=source_id)
-                    except Room.MultipleObjectsReturned:
-                        raise ValueError('Room name is not unique, please provide room guid')
-                    except Room.DoesNotExist:
-                        if self.assembly:
-                            lo = Room(conference=self.conference, pk=source_uuid, assembly=self.assembly)
-                        else:
-                            raise ValueError('Cannot create room for wildcard schedule source.')
-
-                elif mapping_type == ScheduleSourceMapping.MappingType.EVENT:
-                    assembly = self.assembly
-                    if assembly is None:
-                        # wildcard schedulesource: lookup assembly based on referenced room
-                        if hints and 'room_lookup' in hints and 'room_name' in hints:
-                            r = hints['room_lookup'](hints['room_name'])
-                            assembly = r.assembly
-
+            try:
+                # we could not find the mapping, but we have a source_uuid -> try to find the local object by that
+                mapping = self.mappings.get(mapping_type=mapping_type, local_id=source_uuid)
+                return mapping, False
+            except ObjectDoesNotExist:
+                lo = None
+                if create_local_object:
+                    if mapping_type == ScheduleSourceMapping.MappingType.ROOM:
+                        try:
+                            if source_uuid:
+                                lo = Room.objects.get(conference=self.conference, pk=source_uuid)
+                            elif self.assembly:
+                                lo = Room.objects.get(conference=self.conference, assembly=self.assembly, name__iexact=source_id)
+                            else:
+                                lo = Room.objects.get(conference=self.conference, name__iexact=source_id)
+                        except Room.MultipleObjectsReturned:
+                            raise ValueError('Room name is not unique, please provide room guid')
+                        except Room.DoesNotExist:
+                            if self.assembly:
+                                lo = Room(conference=self.conference, pk=source_uuid, assembly=self.assembly)
+                            else:
+                                raise ValueError('Cannot create room for wildcard schedule source.')
+
+                    elif mapping_type == ScheduleSourceMapping.MappingType.EVENT:
+                        assembly = self.assembly
                         if assembly is None:
-                            raise NotImplementedError('Event on wildcard schedulesource could not be matched to an assembly.')
-
-                    lo = Event(conference=self.conference, pk=source_uuid, assembly=assembly)
-
-                elif mapping_type == ScheduleSourceMapping.MappingType.SPEAKER:
-                    lo, _ = self._get_or_create_speaker(
-                        mail_guid=source_uuid,
-                        name=hints.get('name'),
-                        addresses=hints.get('addresses'),
-                    )
-
-            mapping = self.mappings.create(
-                mapping_type=mapping_type,
-                source_id=source_id,
-                local_id=lo.pk,
-                local_object=lo,
-            )
-            return mapping, True
+                            # wildcard schedulesource: lookup assembly based on referenced room
+                            if hints and 'room_lookup' in hints and 'room_name' in hints:
+                                r = hints['room_lookup'](hints['room_name'])
+                                assembly = r.assembly
+
+                            if assembly is None:
+                                raise NotImplementedError('Event on wildcard schedulesource could not be matched to an assembly.')
+
+                        lo = Event(conference=self.conference, pk=source_uuid, assembly=assembly)
+
+                    elif mapping_type == ScheduleSourceMapping.MappingType.SPEAKER:
+                        lo, _ = self._get_or_create_speaker(
+                            mail_guid=source_uuid,
+                            name=hints.get('name'),
+                            addresses=hints.get('addresses'),
+                        )
+
+                mapping = self.mappings.create(
+                    mapping_type=mapping_type,
+                    source_id=source_id,
+                    local_id=lo.pk,
+                    local_object=lo,
+                )
+                return mapping, True
 
     def _load_dataitem(self, activity: list, item: dict, item_source_id: str, item_type: str, expected_items: list, items: dict, from_dict_args: dict) -> str:
         if item_source_id is None:
@@ -549,36 +554,41 @@ class ScheduleSource(models.Model):
                 logging.exception('Import on ScheduleSource %s encountered exception on loading room "%s".', self.pk, r_id)
 
         # then load events
-        for e_id, e in data['events'].items():
-            try:
-                if replace_conference_slug_prefix and e.get('slug', '').startswith(replace_conference_slug_prefix):
-                    e['slug'] = self.conference.slug + e['slug'][len(replace_conference_slug_prefix) :]
+        for e_id, entries in data['events'].items():
+            has_multiple_slots = isinstance(entries, list)
+            # `entries` can either by an single event of a group of events with the same id
+            for e in entries if has_multiple_slots else [entries]:
+                source_id = e.get('guid') if has_multiple_slots else e_id
+                try:
+                    if replace_conference_slug_prefix and e.get('slug', '').startswith(replace_conference_slug_prefix):
+                        e['slug'] = self.conference.slug + e['slug'][len(replace_conference_slug_prefix) :]
+
+                    self._load_dataitem(
+                        activity=activity,
+                        item=e,
+                        item_source_id=source_id,
+                        item_type='event',
+                        expected_items=expected_events,
+                        items=events,
+                        from_dict_args={
+                            'allow_kind': self.assembly.is_official if self.assembly else False,  # TODO: lookup assembly's room if not given
+                            'allow_track': allow_track,  # TODO
+                            'room_lookup': rooms.get,
+                            'speaker_lookup': speaker_lookup,
+                        },
+                    )
 
-                self._load_dataitem(
-                    activity=activity,
-                    item=e,
-                    item_source_id=e_id,
-                    item_type='event',
-                    expected_items=expected_events,
-                    items=events,
-                    from_dict_args={
-                        'allow_kind': self.assembly.is_official if self.assembly else False,  # TODO: lookup assembly's room if not given
-                        'allow_track': allow_track,  # TODO
-                        'room_lookup': rooms.get,
-                        'speaker_lookup': speaker_lookup,
-                    },
-                )
-            except Exception as err:
-                activity.append(
-                    {
-                        'action': 'error',
-                        'type': 'event',
-                        'source_id': e_id,
-                        'local_id': e.get('uuid', None),
-                        'message': str(err),
-                    }
-                )
-                logging.exception('Import on ScheduleSource %s encountered exception on loading event "%s".', self.pk, e_id)
+                except Exception as err:
+                    activity.append(
+                        {
+                            'action': 'error',
+                            'type': 'event',
+                            'source_id': source_id,
+                            'local_id': e.get('guid', None),
+                            'message': str(err),
+                        }
+                    )
+                    logging.exception('Import on ScheduleSource %s encountered exception on loading event "%s".', self.pk, e_id)
 
         # flag the non-loaded rooms as 'missing'
         for room_id in expected_rooms:
diff --git a/src/core/schedules/schedulejson.py b/src/core/schedules/schedulejson.py
index f6c92eaab1bd7d66db490e0ba30d121b2c68ce73..cb13339cc48f083859464b668ed48c4f46ca969b 100644
--- a/src/core/schedules/schedulejson.py
+++ b/src/core/schedules/schedulejson.py
@@ -69,31 +69,45 @@ class ScheduleJSONSupport(BaseScheduleSupport):
                 return f'{host}{uri}'
             return uri
 
+        def format_event(e):
+            """
+            transforms an raw ScheduleJSON event into a HUB event dict, which can ne used in Event.from_dict()
+
+            :param e: event dict from ScheduleJSON class
+            :return: dict with data for Event.from_dict()
+            """
+            return {
+                'guid': e.get('guid'),
+                'slug': e.get('slug').split(f"{e.get('id')}-")[1][0:150].strip('-') or e.get('slug')[0:150].strip('-'),
+                'name': e.get('title'),
+                'language': e.get('language'),
+                'abstract': e.get('abstract') or '',
+                'description': e.get('description') or '',
+                'description_en': e.get('description') or '',
+                'description_de': schedule_de.event(e.get('guid')).get('description') or '',
+                'track': e.get('track'),
+                'room': e.get('room'),
+                'schedule_start': e.get('date'),
+                'schedule_duration': str(schedule_time_to_timedelta(e.get('duration'))),
+                'is_public': True,
+                'kind': kind,
+                'speakers': e.get('persons', []),
+                'banner_image_url': ensure_full_url(e.get('logo')),
+                'additional_data': filter_additional_data(e, self.computed_data(e), other_fields_to_drop),
+            }
+
+        def format_group(events):
+            # if the submission has only one slot, we return a single event - to be backwards compatible
+            if len(events) == 1:
+                return format_event(events[0])
+
+            # if we have a submisson with multiple slots, we return a list of events
+            return [format_event(e) for e in events]
+
         return {
             'version': schedule.version(),
             'rooms': {r['name']: r for r in schedule.rooms()},
-            'events': {
-                e.get('id'): {
-                    'guid': e.get('guid'),
-                    'slug': e.get('slug').split(f"{e.get('id')}-")[1][0:150].strip('-') or e.get('slug')[0:150].strip('-'),
-                    'name': e.get('title'),
-                    'language': e.get('language'),
-                    'abstract': e.get('abstract') or '',
-                    'description': e.get('description') or '',
-                    'description_en': e.get('description') or '',
-                    'description_de': schedule_de.event(e.get('guid')).get('description') or '',
-                    'track': e.get('track'),
-                    'room': e.get('room'),
-                    'schedule_start': e.get('date'),
-                    'schedule_duration': str(schedule_time_to_timedelta(e.get('duration'))),
-                    'is_public': True,
-                    'kind': kind,
-                    'speakers': e.get('persons', []),
-                    'banner_image_url': ensure_full_url(e.get('logo')),
-                    'additional_data': filter_additional_data(e, self.computed_data(e), other_fields_to_drop),
-                }
-                for e in schedule.events()
-            },
+            'events': {k: format_group(e) for k, e in schedule.events_grouped(by='id').items()},
         }
 
     def computed_data(self, event: dict):
@@ -171,6 +185,14 @@ class ScheduleJSON:
             for room in day.get('rooms'):
                 yield from day.get('rooms')[room]
 
+    def events_grouped(self, by='id'):
+        groups = {}
+        for event in self.events():
+            if event[by] not in groups:
+                groups[event[by]] = []
+            groups[event[by]].append(event)
+        return groups
+
     def event(self, guid):
         if guid in self._events:
             return self._events[guid]
diff --git a/src/hub/settings/base.py b/src/hub/settings/base.py
index ddfc524ffb7179449d24ed8bfc128177a73b91cd..64a6e524415d1484deee53071c071d1b6491d577 100644
--- a/src/hub/settings/base.py
+++ b/src/hub/settings/base.py
@@ -118,6 +118,7 @@ env = environ.FileAwareEnv(
     CSP_BASE_URI=(list, ["'self'"]),
     CSP_INCLUDE_NONCE_IN=(list, ['script-src']),
     ADDITIONAL_LINK_PROTOCOLS=(dict, {}),
+    BLOCK_DUPLICATE_EVENT_NAMES=(bool, False),
 )
 
 
@@ -546,6 +547,12 @@ METRICS_SERVER_IPS = env('METRICS_SERVER_IPS')
 
 ADDITIONAL_LINK_PROTOCOLS = env.dict('ADDITIONAL_LINK_PROTOCOLS', cast={'value': str})
 
+# ----------------------------------
+# Internal Schedule Support
+# ----------------------------------
+
+BLOCK_DUPLICATE_EVENT_NAMES = env.bool('BLOCK_DUPLICATE_EVENT_NAMES')
+
 # ----------------------------------
 # External Schedule Support
 # ----------------------------------