diff --git a/docs/clmc-service.md b/docs/clmc-service.md
index 69b1ac091d307d9094d6015a61df33043ad833cb..8721c7251ff42c9b1d7f4c493a31e3dfd37143ef 100644
--- a/docs/clmc-service.md
+++ b/docs/clmc-service.md
@@ -144,6 +144,15 @@ with **/clmc-service** so that the nginx reverse proxy server (listening on port
         }
         ```
 
+* **PUT** ***/alerts***
+
+    This API method can be used to send an alert specification document, which is then used by the CLMC service to create or update
+    alert tasks and subscribe alert handlers to those tasks in Kapacitor. For further information on the alert specification
+    document, please check the [CLMC Alert Specification Documentation](AlertsSpecification.md).
+    
+    The request/response format of this method is the same as the **POST /alerts** API endpoint with the only difference being that existing alert tasks
+    or handlers will be re-created rather than returning a duplication error.
+
 * **GET** ***/alerts/{sfc_id}/{sfc_instance_id}***
 
     This API method can be used to fetch all alerts that are registered for a specific service function chain instance identified
diff --git a/src/service/clmcservice/alertsapi/tests.py b/src/service/clmcservice/alertsapi/tests.py
index 59da0fbc681f5c5b8c66dc811bebaff4d064d9da..64683d24aa51ba2a99c2896797fb971d5acc8e3a 100644
--- a/src/service/clmcservice/alertsapi/tests.py
+++ b/src/service/clmcservice/alertsapi/tests.py
@@ -149,14 +149,15 @@ class TestAlertsConfigurationAPI(object):
 
     def test_alerts_config_api_post(self, app_config):
         """
-        Tests the POST API endpoint of the alerts configuration API responsible for receiving alerts specifications.
+        Tests the POST API endpoint of the alerts configuration API responsible for creating alerts.
 
         Test steps are:
             * Traverse all valid TOSCA Alerts Specifications and TOSCA Resource Specifications in the
                 src/service/clmcservice/resources/tosca/test-data/clmc-validator/valid and src/service/clmcservice/resources/tosca/test-data/tosca-parser/valid folders
-            * Send a valid TOSCA Alert Specification to the view responsible for configuring Kapacitor and creating alerts
+            * Send a valid TOSCA Alert Specification to the view responsible for configuring Kapacitor and creating alerts (POST request)
             * Check that Kapacitor alerts, topics and handlers are created with the correct identifier and arguments
-            * Check that the API returns the duplication errors if the same alerts specification is sent
+            * Check that the API returns the duplication errors if the same alerts specification is sent through a POST request
+            * Check that the API returns no duplication errors if the same alerts specification is sent through a PUT request
             * Clean up the registered alerts
 
         :param app_config: fixture for setUp/tearDown of the web service registry
@@ -222,8 +223,8 @@ class TestAlertsConfigurationAPI(object):
             # send the same request but as a PUT method instead of POST
             with open(alert_spec_abs_path) as alert_spec:
                 with open(valid_resource_spec_abs_path) as valid_resource_spec:
-                    request.POST['alert-spec'] = FieldStorageMock(alerts_test_file, alert_spec)  # a simple mock class is used to mimic the FieldStorage class
-                    request.POST['resource-spec'] = FieldStorageMock(valid_resources_test_file, valid_resource_spec)
+                    request.params['alert-spec'] = FieldStorageMock(alerts_test_file, alert_spec)  # a simple mock class is used to mimic the FieldStorage class
+                    request.params['resource-spec'] = FieldStorageMock(valid_resources_test_file, valid_resource_spec)
                     clmc_service_response = AlertsConfigurationAPI(request).put_alerts_specification()
 
             # no errors are expected now, since the PUT request must update existing alerts
@@ -238,6 +239,52 @@ class TestAlertsConfigurationAPI(object):
             # clean-up in the end of the test
             clean_kapacitor_alerts(alerts, kapacitor_host, kapacitor_port)
 
+    def test_alerts_config_api_put(self, app_config):
+        """
+        Tests the PUT API endpoint of the alerts configuration API responsible for creating or updating alerts.
+
+        Test steps are:
+            * Traverse all valid TOSCA Alerts Specifications and TOSCA Resource Specifications in the
+                src/service/clmcservice/resources/tosca/test-data/clmc-validator/valid and src/service/clmcservice/resources/tosca/test-data/tosca-parser/valid folders
+            * Send a valid TOSCA Alert Specification to the view responsible for configuring Kapacitor and creating/updating alerts (PUT request)
+            * Check that Kapacitor alerts, topics and handlers are created with the correct identifier and arguments
+            * Clean up the registered alerts
+
+        :param app_config: fixture for setUp/tearDown of the web service registry
+        """
+
+        kapacitor_host = self.config.registry.settings["kapacitor_host"]
+        kapacitor_port = self.config.registry.settings["kapacitor_port"]
+
+        # test all of the test files provided by the path_generator_testfiles function, ignoring the last result, which is invalid resource spec. files
+        for alert_spec_file_paths, valid_resource_spec_file_paths, _ in path_generator_testfiles():
+            alert_spec_abs_path, alerts_test_file = alert_spec_file_paths  # absolute path and name of the alerts spec. file
+            resource_spec_abs_path, resources_test_file = valid_resource_spec_file_paths  # absolute path and name of a valid resource spec. file
+
+            with open(alert_spec_abs_path) as alert_spec:
+                # extract alert configuration data
+                sfc, sfc_instance, alerts = extract_alert_configuration_data(alert_spec, self.config.registry.settings["sfemc_fqdn"], self.config.registry.settings["sfemc_port"])
+                alert_spec.seek(0)  # reset the read pointer to the beginning again (the extraction in the previous step had to read the full file)
+
+                # send valid alert and resource spec to create the alerts with a PUT request (can be used for updating or creating)
+                with open(resource_spec_abs_path) as resource_spec:
+                    request = testing.DummyRequest()
+                    request.params['alert-spec'] = FieldStorageMock(alerts_test_file, alert_spec)  # a simple mock class is used to mimic the FieldStorage class
+                    request.params['resource-spec'] = FieldStorageMock(resources_test_file, resource_spec)
+                    clmc_service_response = AlertsConfigurationAPI(request).put_alerts_specification()
+
+            # no errors are expected now, since the PUT request must update existing alerts
+            assert (sfc, sfc_instance) == (clmc_service_response["service_function_chain_id"], clmc_service_response["service_function_chain_instance_id"]), \
+                "Incorrect extraction of metadata for file {0}".format(alerts_test_file)
+            assert "triggers_specification_errors" not in clmc_service_response, "Unexpected error was returned for triggers specification"
+            assert "triggers_action_errors" not in clmc_service_response, "Unexpected error was returned for handlers specification"
+
+            # traverse through all alerts and check that they were created by the PUT request
+            check_kapacitor_alerts(alerts, kapacitor_host, kapacitor_port, alerts_test_file)
+
+            # clean-up in the end of the test
+            clean_kapacitor_alerts(alerts, kapacitor_host, kapacitor_port)
+
     def test_alerts_config_api_get(self, app_config):
         """
         Tests the GET API endpoint of the alerts configuration API responsible for fetching registered alerts for a specific SFC instance.
@@ -409,6 +456,7 @@ class TestAlertsConfigurationAPI(object):
             assert response == {"deleted_alerts": [], "deleted_handlers": []}, "Incorrect response after a second delete"
 
 
+# The implementation below is for utility methods and classes used in the tests' implementation.
 class FieldStorageMock(object):
 
     def __init__(self, filename, file):
diff --git a/src/service/clmcservice/alertsapi/views.py b/src/service/clmcservice/alertsapi/views.py
index ddb1f71a47cf8177cd561639fd01fb589beac193..c984dc818cbc37b62b33d3abaae8bea229bd8aa2 100644
--- a/src/service/clmcservice/alertsapi/views.py
+++ b/src/service/clmcservice/alertsapi/views.py
@@ -63,6 +63,7 @@ class AlertsConfigurationAPI(object):
     @view_config(route_name='alerts_configuration', request_method='GET')
     def get_alerts_hash(self):
         """
+        (DEPRECATED - there is a GET /alerts/<sfc>/<sfc_instance> API method)
         Retrieves hash value for alerts task, topic and handlers based on sfc, sfci, policy and trigger IDs
         """
 
@@ -238,8 +239,12 @@ class AlertsConfigurationAPI(object):
 
         kapacitor_host, kapacitor_port = self.request.registry.settings['kapacitor_host'], self.request.registry.settings['kapacitor_port']
 
-        alert_spec_reference = self.request.POST.get('alert-spec')
-        resource_spec_reference = self.request.POST.get('resource-spec')
+        if patch_duplicates:  # implying a PUT request
+            alert_spec_reference = self.request.params.get('alert-spec')
+            resource_spec_reference = self.request.params.get('resource-spec')
+        else:  # implying a POST request
+            alert_spec_reference = self.request.POST.get('alert-spec')
+            resource_spec_reference = self.request.POST.get('resource-spec')
 
         # parse the resource specification file and extract the required information
         resource_spec_sfc, resource_spec_sfc_instance, resource_spec_policy_triggers = self._parse_resource_spec(resource_spec_reference)
@@ -469,6 +474,8 @@ class AlertsConfigurationAPI(object):
                 if patch_duplicates and get(kapacitor_api_handlers_instance_url).status_code == 200:
                     # this will only happen if the patch_duplicates flag is set to True
                     delete(kapacitor_api_handlers_instance_url)
+                    # an alternative is to use the PATCH API endpoint instead of deleting and creating it again, however,
+                    # using the PATCH method requires the task to be disabled and re-enabled for changes to take effect (more HTTP requests)
                     response = post(kapacitor_api_handlers_url, json=kapacitor_http_request_body)
                     response_content = response.json()
                     capture_error = response_content.get("error", "") != ""
diff --git a/src/test/clmctest/alerts/test_alerts.py b/src/test/clmctest/alerts/test_alerts.py
index 9faf8b79e08e6f09980aa0d21b9cca2a08813b2e..1adaad618b61341eca90f6d5206521ec2b0aa0a2 100644
--- a/src/test/clmctest/alerts/test_alerts.py
+++ b/src/test/clmctest/alerts/test_alerts.py
@@ -21,9 +21,9 @@
 ##      Created Date :          22-08-2018
 ##      Created for Project :   FLAME
 """
-
+import datetime
 from time import sleep, strptime
-from requests import post, get, delete
+from requests import post, get, delete, put
 from os import listdir
 from os.path import join, dirname
 from json import load
@@ -208,3 +208,86 @@ class TestAlerts(object):
                                                                                                          {"policy": "scale_nginx_policy", "trigger": "increase_in_running_processes", "handler": "http://172.40.231.200:9999/"},
                                                                                                          {"policy": "deadman_policy", "trigger": "no_measurements", "handler": "http://172.40.231.200:9999/"}], \
             "Incorrect list of deleted handlers"
+
+    def test_alerts_update_request(self, rspec_config):
+        """
+        Test is implemented using the following steps:
+            * Send to clmc service a POST request with TOSCA alert spec. and resource spec. files
+            * Send to clmc service a PUT request with TOSCA alert spec. and resource spec. files
+            * Check that the alerts have a "created" timestamp that is later than the timestamp of the alerts during the POST request,
+                implying that the alerts were re-created during the PUT request
+
+        :param rspec_config: fixture from conftest.py
+        """
+
+        clmc_service_host = None
+        for host in rspec_config:
+            if host["name"] == "clmc-service":
+                clmc_service_host = host["ip_address"]
+                break
+
+        # create the alerts with a POST request
+        print("Sending alerts specification to clmc service...")
+        alerts_spec = join(dirname(__file__), "alerts_test_config.yaml")
+        resources_spec = join(dirname(__file__), "resources_test_config.yaml")
+
+        with open(alerts_spec, 'rb') as alerts:
+            with open(resources_spec, 'rb') as resources:
+                files = {'alert-spec': alerts, 'resource-spec': resources}
+                response = post("http://{0}/clmc-service/alerts".format(clmc_service_host), files=files)
+        assert response.status_code == 200
+        clmc_service_response = response.json()
+        assert "triggers_specification_errors" not in clmc_service_response, "Unexpected error was returned for triggers specification"
+        assert "triggers_action_errors" not in clmc_service_response, "Unexpected error was returned for handlers specification"
+        sfc, sfc_instance = "MS_Template_1", "MS_Template_1_1"
+        assert (sfc, sfc_instance) == (clmc_service_response["service_function_chain_id"], clmc_service_response["service_function_chain_instance_id"])
+        print("Alert spec sent successfully")
+
+        # find the latest timestamp of the registered alerts
+        max_post_timestamp = 0
+        tasks = get("http://{0}/kapacitor/v1/tasks".format(clmc_service_host)).json()["tasks"]
+        for task in tasks:
+            # get the configured variables of this alert
+            task_config = task["vars"]
+            # if configured for this SFC instance
+            if task_config["sfc"]["value"] == sfc and task_config["sfci"]["value"] == sfc_instance:
+                created_datestr = task["created"][:26]  # ignore the timezone and only take the first 6 digits of the microseconds
+                task_created_timestamp = datetime.datetime.strptime(created_datestr, "%Y-%m-%dT%H:%M:%S.%f")
+                max_post_timestamp = max(max_post_timestamp, task_created_timestamp.timestamp())
+
+        print("Sleeping 2 seconds to ensure a difference between the timestamps when creating the alerts and when updating them...")
+        sleep(2)
+
+        # update the alerts with a PUT request and check that the "created" metadata is updated implying that the alerts were recreated
+        print("Sending alerts specification to clmc service for updating...")
+        with open(alerts_spec, 'rb') as alerts:
+            with open(resources_spec, 'rb') as resources:
+                files = {'alert-spec': alerts, 'resource-spec': resources}
+                response = put("http://{0}/clmc-service/alerts".format(clmc_service_host), files=files)
+        assert response.status_code == 200
+        clmc_service_response = response.json()
+        assert "triggers_specification_errors" not in clmc_service_response, "Unexpected error was returned for triggers specification"
+        assert "triggers_action_errors" not in clmc_service_response, "Unexpected error was returned for handlers specification"
+        sfc, sfc_instance = "MS_Template_1", "MS_Template_1_1"
+        assert (sfc, sfc_instance) == (clmc_service_response["service_function_chain_id"], clmc_service_response["service_function_chain_instance_id"])
+        print("Alert spec updated successfully")
+
+        # find the earliest timestamp of the updated alerts
+        min_put_timestamp = float("inf")
+        tasks = get("http://{0}/kapacitor/v1/tasks".format(clmc_service_host)).json()["tasks"]
+        for task in tasks:
+            # get the configured variables of this alert
+            task_config = task["vars"]
+            # if configured for this SFC instance
+            if task_config["sfc"]["value"] == sfc and task_config["sfci"]["value"] == sfc_instance:
+                created_datestr = task["created"][:26]  # ignore the timezone and only take the first 6 digits of the microseconds
+                task_created_timestamp = datetime.datetime.strptime(created_datestr, "%Y-%m-%dT%H:%M:%S.%f")
+                min_put_timestamp = min(min_put_timestamp, task_created_timestamp.timestamp())
+
+        print("Latest timestamp during the POST request", max_post_timestamp, "Earliest timestamp during the PUT request", min_put_timestamp)
+        assert max_post_timestamp < min_put_timestamp, "There is an alert that wasn't updated properly with a PUT request"
+
+        # delete the alerts with a DELETE request
+        with open(alerts_spec, 'rb') as alerts:
+            files = {'alert-spec': alerts}
+            delete("http://{0}/clmc-service/alerts".format(clmc_service_host), files=files)