diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
index fcca3ccbc408a6366c8326add37f1902d4750bbb..7363ab0cc96d0d3a6ef9e2b9a61b938392b05fd9 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
@@ -1274,6 +1274,38 @@ class SchedulingUnitBlueprintViewSet(LOFARViewSet):
         return Response(serializers.SchedulingUnitDraftExtendedSerializer(scheduling_unit_draft_copy, context={'request':request}).data,
                         status=status.HTTP_201_CREATED)
 
+
+    @swagger_auto_schema(responses={201: 'The newly created SchedulingUnitBlueprint-copy with the given station(s) removed',
+                                    403: 'forbidden'},
+                         operation_description="Create a new SchedulingUnitBlueprint-copy with the given station(s) removed, cancel this unit and mark it obsolete")
+    @action(methods=['post'], detail=True, url_name="create_copy_without_given_stations")
+    def create_copy_without_given_stations(self, request, pk=None):
+        scheduling_unit_blueprint = get_object_or_404(models.SchedulingUnitBlueprint, pk=pk)
+        stations_to_be_removed = set([s.upper() for s in request.data['stations_to_be_removed']])
+        with transaction.atomic():
+            # start with creating a draft copy
+            scheduling_unit_draft_copy = create_scheduling_unit_draft_from_scheduling_unit_blueprint(scheduling_unit_blueprint, add_copy_annotations=False)
+
+            # and then remove the given stations from each task
+            for task in scheduling_unit_draft_copy.tasks.all():
+                if 'station_configuration' in task.specifications_doc:
+                    if 'station_groups' in task.specifications_doc['station_configuration']:
+                        for group in task.specifications_doc['station_configuration']['station_groups']:
+                            group['stations'] = sorted(list(set(group['stations']) - stations_to_be_removed))
+                            group['max_nr_missing'] = min(len(group['stations'])-1, group.get('max_nr_missing', 0))
+                        task.save()
+
+            # blueprint the copy
+            scheduling_unit_blueprint_copy = create_scheduling_unit_blueprint_and_tasks_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_copy)
+
+            # and cancel and obsolete the original
+            mark_scheduling_unit_blueprint_as_obsolete(cancel_scheduling_unit_blueprint(scheduling_unit_blueprint))
+
+            # return the new blueprint
+            return Response(serializers.SchedulingUnitBlueprintSerializer(scheduling_unit_blueprint_copy, context={'request':request}).data,
+                            status=status.HTTP_201_CREATED)
+
+
     @swagger_auto_schema(responses={200: 'The system events of this scheduling unit blueprint',
                                     403: 'forbidden'},
                          operation_description="Get the system events of this scheduling unit blueprint.")
diff --git a/SAS/TMSS/backend/test/t_scheduling_units.py b/SAS/TMSS/backend/test/t_scheduling_units.py
index c626dca7ab4c6883cbdd0223d23a8b3e2582616d..a2ec4c2778eabd5efb526b14c964e1744902d777 100644
--- a/SAS/TMSS/backend/test/t_scheduling_units.py
+++ b/SAS/TMSS/backend/test/t_scheduling_units.py
@@ -1650,6 +1650,50 @@ class SchedulingUnitBlueprintIndirectModificationsTestCase(unittest.TestCase):
         # the bug from TMSS-2275 used to be that the unit had status SCHEDULABLE. Now it has the correct status CANCELLED.
         self.assertEqual(models.SchedulingUnitStatus.Choices.CANCELLED.value, unit.status.value)
 
+    def test_create_schedulingunitblueprint_copy_without_given_station(self):
+        with tmss_test_env.create_tmss_client() as client:
+            # create project, and a scheduling set within it
+            project = rest_data_creator.post_data_and_get_response_as_json_object(rest_data_creator.Project(auto_ingest=True, auto_pin=True), '/project/')
+            scheduling_set = rest_data_creator.post_data_and_get_response_as_json_object(rest_data_creator.SchedulingSet(project_url=project['url']), '/scheduling_set/')
+
+            # create 'Simple Observation' scheduling unit draft in the scheduling set
+            observing_strategy_templates = client.get_path_as_json_object('scheduling_unit_observing_strategy_template')
+            strategy_template = next(ost for ost in observing_strategy_templates if ost['name'] == 'Simple Observation')
+            self.assertIsNotNone(strategy_template)
+            scheduling_unit_draft = client.create_scheduling_unit_draft_from_strategy_template(strategy_template['id'], scheduling_set['id'])
+
+            # turn draft into a blueprint
+            scheduling_unit_blueprint = client.create_scheduling_unit_blueprint_and_tasks_and_subtasks_tree(scheduling_unit_draft['id'])
+
+            # schedule it
+            scheduling_unit_blueprint = client.schedule_scheduling_unit(scheduling_unit_blueprint['id'], datetime.utcnow() + timedelta(minutes=10))
+            self.assertEqual(models.SchedulingUnitStatus.Choices.SCHEDULED.value, scheduling_unit_blueprint['status_value'])
+
+            # get the originally specified group(s) of stations
+            scheduling_unit_blueprint = client.get_schedulingunit_blueprint(scheduling_unit_blueprint['id'], include_specifications_doc=True)
+            org_station_groups = scheduling_unit_blueprint['specifications_doc']['tasks']["Observation"]['specifications_doc']['station_configuration']['station_groups']
+
+            stations_to_be_removed = ['CS002', 'CS005']
+
+            # reassure these stations are in the original spec
+            for station in stations_to_be_removed:
+                self.assertIn(station, str(org_station_groups))
+
+            # take out the stations (in a new copy)
+            scheduling_unit_blueprint_copy = client.create_scheduling_unit_blueprint_copy_without_given_stations(scheduling_unit_blueprint['id'], stations_to_be_removed)
+
+            # check it
+            scheduling_unit_blueprint_copy = client.get_schedulingunit_blueprint(scheduling_unit_blueprint_copy['id'], include_specifications_doc=True)
+            self.assertNotEqual(scheduling_unit_blueprint['id'], scheduling_unit_blueprint_copy['id'])
+
+            # Check the core feature: are the stations taken out of the new copy?
+            new_station_groups = scheduling_unit_blueprint_copy['specifications_doc']['tasks']["Observation"]['specifications_doc']['station_configuration']['station_groups']
+            for station in stations_to_be_removed:
+                self.assertNotIn(station, str(new_station_groups))
+
+            # check the status of the original, is it cancelled and obsolete?
+            scheduling_unit_blueprint = client.get_schedulingunit_blueprint(scheduling_unit_blueprint['id'], include_specifications_doc=True)
+            self.assertEqual(models.SchedulingUnitStatus.Choices.CANCELLED.value, scheduling_unit_blueprint['status_value'])
 
 
 if __name__ == "__main__":
diff --git a/SAS/TMSS/client/lib/tmss_http_rest_client.py b/SAS/TMSS/client/lib/tmss_http_rest_client.py
index fbe748499c9a7a3fc98efee4cfd9add587af47a1..e734e5a17749f388fa8e459327cc34d1cef95ca8 100644
--- a/SAS/TMSS/client/lib/tmss_http_rest_client.py
+++ b/SAS/TMSS/client/lib/tmss_http_rest_client.py
@@ -644,7 +644,7 @@ class TMSSsession(object):
     def copy_scheduling_unit_blueprint_specifications_doc_back_into_draft(self, scheduling_unit_blueprint_id: int, including_copies_for_failed_tasks: bool=False, retry_count: int=0) -> {}:
         """Copy this blueprint's specifications_doc back into the originating draft scheduling unit.
         if including_copies_for_failed_tasks==True then extend the graph specification with copies for all failed tasks and link them.
-        returns the scheduling_unit_blueprint (which containts a link to the draft with the updated specifications_doc), or raises."""
+        returns the scheduling_unit_blueprint (which contains a link to the draft with the updated specifications_doc), or raises."""
         action = 'copy_specifications_doc_including_copies_for_failed_tasks_back_into_draft' if including_copies_for_failed_tasks else 'copy_specifications_doc_back_into_draft'
         return self.post_to_path_and_get_result_as_json_object('scheduling_unit_blueprint/%s/%s' % (scheduling_unit_blueprint_id, action), retry_count=retry_count)
 
@@ -678,6 +678,11 @@ class TMSSsession(object):
         returns the copied task_draft, or raises."""
         return self.post_to_path_and_get_result_as_json_object('task_draft/%s/copy' % (task_draft_id, ), retry_count=retry_count)
 
+    def create_scheduling_unit_blueprint_copy_without_given_stations(self, scheduling_unit_blueprint_id: int, stations_to_be_removed: list, retry_count: int=0) -> {}:
+        return self.post_to_path_and_get_result_as_json_object('scheduling_unit_blueprint/%s/create_copy_without_given_stations' % (scheduling_unit_blueprint_id, ),
+                                                               json_data={'stations_to_be_removed': stations_to_be_removed},
+                                                               retry_count=retry_count)
+
 
     def get_scheduling_set(self, scheduling_set_id: str) -> dict:
         '''get the schedulingunit_set as dict for the given scheduling_set_id.'''