diff --git a/build.gradle b/build.gradle
index 50fa4f247683f3442bb8d8f1aca9e6c6f00c0b74..a20cb0792087167795f0e9cc3816c03eb44214ab 100644
--- a/build.gradle
+++ b/build.gradle
@@ -88,7 +88,6 @@ dependencies {
     implementation('org.springframework.boot:spring-boot-starter-mail')
     implementation('org.springframework.boot:spring-boot-starter-data-jpa')
     implementation('org.springframework.boot:spring-boot-starter-actuator')
-    implementation('org.springframework.boot:spring-boot-devtools')
     implementation('org.springframework.boot:spring-boot-starter-quartz')
     implementation('org.springframework.boot:spring-boot-starter-validation')
     implementation 'org.springframework.boot:spring-boot-starter-cache'
diff --git a/src/main/java/net/geant/nmaas/orchestration/jobs/DomainGroupJob.java b/src/main/java/net/geant/nmaas/orchestration/jobs/DomainGroupJob.java
new file mode 100644
index 0000000000000000000000000000000000000000..7fe42451ebba65a1061e0981e789e9c0d823826a
--- /dev/null
+++ b/src/main/java/net/geant/nmaas/orchestration/jobs/DomainGroupJob.java
@@ -0,0 +1,55 @@
+package net.geant.nmaas.orchestration.jobs;
+
+import lombok.extern.slf4j.Slf4j;
+import net.geant.nmaas.orchestration.exceptions.WebServiceCommunicationException;
+import net.geant.nmaas.portal.api.domain.DomainGroupView;
+import net.geant.nmaas.portal.api.domain.DomainGroupWebhookDto;
+import net.geant.nmaas.portal.api.domain.WebhookEventDto;
+import net.geant.nmaas.portal.api.exception.MissingElementException;
+import net.geant.nmaas.portal.persistent.entity.WebhookEventType;
+import net.geant.nmaas.portal.service.WebhookEventService;
+import org.modelmapper.ModelMapper;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestClient;
+
+import java.security.GeneralSecurityException;
+
+@Slf4j
+@Component
+public class DomainGroupJob extends WebhookJob {
+
+    @Autowired
+    public DomainGroupJob(RestClient restClient, WebhookEventService webhookEventService, ModelMapper modelMapper) {
+        super(restClient, webhookEventService, modelMapper);
+    }
+
+    @Override
+    public void execute(JobExecutionContext context) throws JobExecutionException {
+        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
+        Long webhookId = dataMap.getLong("webhookId");
+        String action = dataMap.getString("action");
+        DomainGroupView domainGroup = (DomainGroupView) dataMap.get("domainGroup");
+
+        try {
+            WebhookEventDto webhook = webhookEventService.getById(webhookId);
+            if (!WebhookEventType.DOMAIN_GROUP_CHANGE.equals(webhook.getEventType())) {
+                log.warn("Webhook's event type with id {} has been updated. DomainGroupJob is abandoned", webhookId);
+                return;
+            }
+            DomainGroupWebhookDto view = new DomainGroupWebhookDto(domainGroup, action);
+            callWebhook(webhook, view);
+        } catch (GeneralSecurityException e) {
+            log.error("Failed to decrypt webhook with id {}", webhookId);
+            throw new JobExecutionException("Failed webhook decryption");
+        } catch (MissingElementException e) {
+            log.warn("Webhook does not exist. DomainGroupJob is abandoned");
+        } catch (WebServiceCommunicationException e) {
+            log.error("Failed to communicate with external system for the webhoook of domain group with id {}", domainGroup.getId());
+            throw new JobExecutionException("Failed communication with external system");
+        }
+    }
+}
diff --git a/src/main/java/net/geant/nmaas/portal/api/domain/ApplicationStatePerDomainView.java b/src/main/java/net/geant/nmaas/portal/api/domain/ApplicationStatePerDomainView.java
index 7ed46a20911b349308d0eebcdb3bbd0b93c36dcd..ccce6b28f866030a0897efc855ff62458a58f250 100644
--- a/src/main/java/net/geant/nmaas/portal/api/domain/ApplicationStatePerDomainView.java
+++ b/src/main/java/net/geant/nmaas/portal/api/domain/ApplicationStatePerDomainView.java
@@ -3,9 +3,11 @@ package net.geant.nmaas.portal.api.domain;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.io.Serializable;
+
 @Getter
 @Setter
-public class ApplicationStatePerDomainView {
+public class ApplicationStatePerDomainView  implements Serializable {
     Long applicationBaseId;
     String applicationBaseName;
     boolean enabled;
diff --git a/src/main/java/net/geant/nmaas/portal/api/domain/DomainBase.java b/src/main/java/net/geant/nmaas/portal/api/domain/DomainBase.java
index 9bfd26a5b81a42a51a4c4dfe7c763ec4214a4e22..cf77585ec84652b6db6cbc25f83f9b9a8fe00981 100644
--- a/src/main/java/net/geant/nmaas/portal/api/domain/DomainBase.java
+++ b/src/main/java/net/geant/nmaas/portal/api/domain/DomainBase.java
@@ -4,10 +4,12 @@ import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 
+import java.io.Serializable;
+
 @Getter
 @Setter
 @NoArgsConstructor
-public class DomainBase {
+public class DomainBase  implements Serializable {
 
     Long id;
     String name;
diff --git a/src/main/java/net/geant/nmaas/portal/api/domain/DomainGroupView.java b/src/main/java/net/geant/nmaas/portal/api/domain/DomainGroupView.java
index 2e40d9005a04d0013f0e5867c3fffcd1ac2a7fed..a5855816dd63f59af5c3088119d4c7230cbe539a 100644
--- a/src/main/java/net/geant/nmaas/portal/api/domain/DomainGroupView.java
+++ b/src/main/java/net/geant/nmaas/portal/api/domain/DomainGroupView.java
@@ -6,6 +6,7 @@ import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -13,7 +14,7 @@ import java.util.List;
 @NoArgsConstructor
 @Getter
 @Setter
-public class DomainGroupView {
+public class DomainGroupView implements Serializable {
 
     @NotNull
     private Long id;
diff --git a/src/main/java/net/geant/nmaas/portal/api/domain/DomainGroupWebhookDto.java b/src/main/java/net/geant/nmaas/portal/api/domain/DomainGroupWebhookDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..75685180793fe87af636eabd3623888851ca0aeb
--- /dev/null
+++ b/src/main/java/net/geant/nmaas/portal/api/domain/DomainGroupWebhookDto.java
@@ -0,0 +1,14 @@
+package net.geant.nmaas.portal.api.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@AllArgsConstructor
+@Getter
+@Setter
+public class DomainGroupWebhookDto {
+
+    private DomainGroupView domainGroup;
+    private String action;
+}
diff --git a/src/main/java/net/geant/nmaas/portal/persistent/entity/DomainGroup.java b/src/main/java/net/geant/nmaas/portal/persistent/entity/DomainGroup.java
index 186f96dcf0397919d061d6c389ae6f42e4bfb751..74d554474081b8ed4233bba8c9d4b2ae03ac7669 100644
--- a/src/main/java/net/geant/nmaas/portal/persistent/entity/DomainGroup.java
+++ b/src/main/java/net/geant/nmaas/portal/persistent/entity/DomainGroup.java
@@ -67,7 +67,7 @@ public class DomainGroup implements Serializable {
     public DomainGroup(String name, String codename) {
         super();
         this.name = name;
-        this.codename = name;
+        this.codename = codename;
     }
 
     public DomainGroup(Long id, String name, String codename) {
diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java
index 3dbc1baf929b1624f7abf0b246166ea6966ce1e9..2823c728ce858495ce6f708d8968d072848e1503 100644
--- a/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java
+++ b/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java
@@ -2,6 +2,8 @@ package net.geant.nmaas.portal.service.impl;
 
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import net.geant.nmaas.orchestration.jobs.DomainCreationJob;
+import net.geant.nmaas.orchestration.jobs.DomainGroupJob;
 import net.geant.nmaas.portal.api.domain.ApplicationStatePerDomainView;
 import net.geant.nmaas.portal.api.domain.DomainGroupView;
 import net.geant.nmaas.portal.api.exception.MissingElementException;
@@ -11,16 +13,21 @@ import net.geant.nmaas.portal.persistent.entity.ApplicationStatePerDomain;
 import net.geant.nmaas.portal.persistent.entity.Domain;
 import net.geant.nmaas.portal.persistent.entity.DomainGroup;
 import net.geant.nmaas.portal.persistent.entity.User;
+import net.geant.nmaas.portal.persistent.entity.WebhookEventType;
 import net.geant.nmaas.portal.persistent.repositories.DomainGroupRepository;
+import net.geant.nmaas.portal.persistent.repositories.WebhookEventRepository;
 import net.geant.nmaas.portal.service.ApplicationStatePerDomainService;
 import net.geant.nmaas.portal.service.DomainGroupService;
+import net.geant.nmaas.scheduling.ScheduleManager;
 import org.apache.commons.lang3.StringUtils;
 import org.modelmapper.ModelMapper;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -31,6 +38,8 @@ public class DomainGroupServiceImpl implements DomainGroupService {
 
     private final DomainGroupRepository domainGroupRepository;
     private final ApplicationStatePerDomainService applicationStatePerDomainService;
+    private final WebhookEventRepository webhookEventRepository;
+    private final ScheduleManager scheduleManager;
 
 
     private final ModelMapper modelMapper;
@@ -55,6 +64,10 @@ public class DomainGroupServiceImpl implements DomainGroupService {
         DomainGroup domainGroupEntity = modelMapper.map(domainGroup, DomainGroup.class);
         domainGroupEntity.setApplicationStatePerDomain(applicationStatePerDomainList);
         domainGroupEntity = domainGroupRepository.save(domainGroupEntity);
+
+        //call existing webhooks
+        DomainGroupView domainGroupView = modelMapper.map(domainGroupEntity, DomainGroupView.class);
+        webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_GROUP_CHANGE).forEach(id -> scheduleManager.createOneTimeJob(DomainGroupJob.class, "DomainGroup_" + id + "_" + domainGroupView.getId()+ "_" + LocalDateTime.now(), Map.of("webhookId", id, "action", "create","domainGroup",domainGroupView)));
         return modelMapper.map(domainGroupEntity, DomainGroupView.class);
     }
 
@@ -81,6 +94,7 @@ public class DomainGroupServiceImpl implements DomainGroupService {
     @Override
     public void deleteDomainGroup(Long domainGroupId) {
         DomainGroup domainGroup = domainGroupRepository.findById(domainGroupId).orElseThrow();
+        DomainGroupView domainGroupView = modelMapper.map(domainGroup, DomainGroupView.class);
         List<Domain> toRemove = new ArrayList<>(domainGroup.getDomains());
         Iterator<Domain> iterator = toRemove.iterator();
         while (iterator.hasNext()) {
@@ -90,6 +104,8 @@ public class DomainGroupServiceImpl implements DomainGroupService {
             iterator.remove();
         }
         domainGroupRepository.deleteById(domainGroupId);
+        //call existing webhooks
+        webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_GROUP_CHANGE).forEach(id -> scheduleManager.createOneTimeJob(DomainGroupJob.class, "DomainGroup_" + id + "_" + domainGroup.getId()+ "_" + LocalDateTime.now(), Map.of("webhookId", id, "action", "delete","domainGroup",domainGroupView)));
     }
 
     @Override
@@ -128,7 +144,11 @@ public class DomainGroupServiceImpl implements DomainGroupService {
         }
 
         domainGroupRepository.save(domainGroup);
-        return modelMapper.map(domainGroup, DomainGroupView.class);
+
+        //call existing webhooks
+        DomainGroupView domainGroupView = modelMapper.map(domainGroup, DomainGroupView.class);
+        webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_GROUP_CHANGE).forEach(id -> scheduleManager.createOneTimeJob(DomainGroupJob.class, "DomainGroup_" + id + "_" + domainGroupView.getId()+ "_" + LocalDateTime.now(), Map.of("webhookId", id, "action", "update","domainGroup",domainGroupView)));
+        return domainGroupView;
     }
 
     protected void checkParam(DomainGroupView domainGroup) {
diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b1c864275d91a098134dccf3cf1d81e22f73751
--- /dev/null
+++ b/src/test/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceTest.java
@@ -0,0 +1,144 @@
+package net.geant.nmaas.portal.service.impl;
+
+import net.geant.nmaas.orchestration.jobs.DomainGroupJob;
+import net.geant.nmaas.portal.api.domain.DomainGroupView;
+import net.geant.nmaas.portal.persistent.entity.DomainGroup;
+import net.geant.nmaas.portal.persistent.entity.WebhookEvent;
+import net.geant.nmaas.portal.persistent.entity.WebhookEventType;
+import net.geant.nmaas.portal.persistent.repositories.DomainGroupRepository;
+import net.geant.nmaas.portal.persistent.repositories.WebhookEventRepository;
+import net.geant.nmaas.portal.service.ApplicationStatePerDomainService;
+import net.geant.nmaas.portal.service.DomainGroupService;
+import net.geant.nmaas.scheduling.ScheduleManager;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.modelmapper.ModelMapper;
+import org.quartz.JobListener;
+import org.quartz.ListenerManager;
+import org.quartz.Matcher;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class DomainGroupServiceTest {
+
+    DomainGroupRepository domainGroupRepository = mock(DomainGroupRepository.class);
+    ApplicationStatePerDomainService applicationStatePerDomainService = mock(ApplicationStatePerDomainService.class);
+    WebhookEventRepository webhookEventRepository = mock(WebhookEventRepository.class);
+    Scheduler scheduler = mock(Scheduler.class);
+    ListenerManager listenerManager = mock(ListenerManager.class);
+    ScheduleManager scheduleManager;
+    ModelMapper modelMapper = new ModelMapper();
+    DomainGroupService domainGroupService;
+
+    @BeforeEach
+    void setup() {
+        scheduleManager = new ScheduleManager(scheduler);
+        domainGroupService = new DomainGroupServiceImpl(domainGroupRepository, applicationStatePerDomainService, webhookEventRepository, scheduleManager, modelMapper);
+    }
+
+    @Test
+    void shouldCreateDomainGroup() throws SchedulerException {
+        // Setup webhook event
+        WebhookEvent webhookEvent = new WebhookEvent(1L, "webhook", "https://example.com/webhook", WebhookEventType.DOMAIN_GROUP_CHANGE, null, null);
+        when(webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_GROUP_CHANGE))
+                .thenReturn(Stream.of(1L));
+        when(webhookEventRepository.findById(1L))
+                .thenReturn(Optional.of(webhookEvent));
+
+        // Setup domain group
+        String name = "testgroup";
+        String codename = "testgrp";
+        DomainGroup domainGroup = new DomainGroup(name, codename);
+        domainGroup.setId(10L);
+        when(domainGroupRepository.save(any(DomainGroup.class))).thenReturn(domainGroup);
+        when(domainGroupRepository.findById(10L)).thenReturn(Optional.of(domainGroup));
+        when(scheduler.getListenerManager()).thenReturn(listenerManager);
+        doNothing().when(listenerManager).addJobListener(any(JobListener.class), any(Matcher.class));
+
+        // Create domain group
+        DomainGroupView domainGroupView = new DomainGroupView();
+        domainGroupView.setName(name);
+        domainGroupView.setCodename(codename);
+        DomainGroupView result = this.domainGroupService.createDomainGroup(domainGroupView);
+
+        // Verify webhook job was scheduled with correct parameters for creation
+        verify(scheduler, times(1)).scheduleJob(
+            argThat(jobDetail -> 
+                jobDetail.getKey().getName().startsWith("DomainGroup_1_10_") &&
+                jobDetail.getJobClass().equals(DomainGroupJob.class)
+            ),
+            argThat(trigger -> 
+                trigger.getKey().getName().startsWith("DomainGroup_1_10_")
+            )
+        );
+
+        // Verify domain group was created correctly
+        assertThat("Codenames are not the same", result.getCodename().equals(codename));
+        assertThat("Names are not the same", result.getName().equals(name));
+
+        // Update domain group
+        when(webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_GROUP_CHANGE))
+                .thenReturn(Stream.of(1L));
+        when(webhookEventRepository.findById(1L))
+                .thenReturn(Optional.of(webhookEvent));
+        domainGroupView.setCodename(codename + "2");
+        domainGroupView.setId(10L);
+        result = this.domainGroupService.updateDomainGroup(10L, domainGroupView);
+
+        // Verify webhook job was scheduled with correct parameters for update
+        verify(scheduler, times(2)).scheduleJob(
+            argThat(jobDetail -> 
+                jobDetail.getKey().getName().startsWith("DomainGroup_1_10_") &&
+                jobDetail.getJobClass().equals(DomainGroupJob.class)
+            ),
+            argThat(trigger -> 
+                trigger.getKey().getName().startsWith("DomainGroup_1_10_")
+            )
+        );
+
+        // Verify domain group was updated correctly
+        assertThat("Updated codenames are not the same", result.getCodename().equals(codename + "2"));
+        assertThat("Names are not the same after update", result.getName().equals(name));
+    }
+
+    @Test
+    void shouldDeleteDomainGroup() throws SchedulerException {
+        // Setup webhook event
+        WebhookEvent webhookEvent = new WebhookEvent(1L, "webhook", "https://example.com/webhook", WebhookEventType.DOMAIN_GROUP_CHANGE, null, null);
+        when(webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_GROUP_CHANGE))
+                .thenReturn(Stream.of(1L));
+        when(webhookEventRepository.findById(1L))
+                .thenReturn(Optional.of(webhookEvent));
+
+        DomainGroup domainGroup = new DomainGroup("testgroup", "testgrp");
+        domainGroup.setId(10L);
+        when(domainGroupRepository.findById(10L)).thenReturn(Optional.of(domainGroup));
+        when(scheduler.getListenerManager()).thenReturn(listenerManager);
+        doNothing().when(listenerManager).addJobListener(any(JobListener.class), any(Matcher.class));
+        this.domainGroupService.deleteDomainGroup(10L);
+        verify(domainGroupRepository, times(1)).deleteById(10L);
+
+        verify(scheduler, times(1)).scheduleJob(
+                argThat(jobDetail ->
+                        jobDetail.getKey().getName().startsWith("DomainGroup_1_10_") &&
+                                jobDetail.getJobClass().equals(DomainGroupJob.class)
+                ),
+                argThat(trigger ->
+                        trigger.getKey().getName().startsWith("DomainGroup_1_10_")
+                )
+        );
+    }
+}
diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java
index 6f9276d7ff38e95d21e9293a6cd9cad9f5308adf..5fb8cb4c800f2519d943b89133014c20531a2147 100644
--- a/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java
+++ b/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java
@@ -94,8 +94,6 @@ class DomainServiceTest {
     Scheduler scheduler = mock(Scheduler.class);
     ListenerManager listenerManager = mock(ListenerManager.class);
     ScheduleManager scheduleManager;
-    EncryptionService encryptionService = mock(EncryptionService.class);
-    WebhookEventService webhookEventService;
 
     DomainService domainService;
 
@@ -103,15 +101,14 @@ class DomainServiceTest {
     void setup() {
         validator = new DefaultCodenameValidator("[a-z-]{2,12}");
         namespaceValidator = new DefaultCodenameValidator("[a-z-]{0,64}");
-        domainGroupService = new DomainGroupServiceImpl(domainGroupRepository, applicationStatePerDomainService, modelMapper);
         scheduleManager = new ScheduleManager( scheduler);
+        domainGroupService = new DomainGroupServiceImpl(domainGroupRepository, applicationStatePerDomainService, webhookEventRepository, scheduleManager, modelMapper);
         domainService = new DomainServiceImpl(validator,
                 namespaceValidator, domainRepository,
                 domainDcnDetailsRepository, domainTechDetailsRepository, userService,
                 userRoleRepo, dcnRepositoryManager,
                 modelMapper, applicationStatePerDomainService, domainGroupService, eventPublisher, domainAnnotationsRepository, webhookEventRepository, scheduleManager);
         ((DomainServiceImpl) domainService).globalDomain = "GLOBAL";
-        webhookEventService = new WebhookEventService(webhookEventRepository, encryptionService, modelMapper);
     }
 
     @Test