diff --git a/src/main/java/net/geant/nmaas/orchestration/jobs/DomainCreationJob.java b/src/main/java/net/geant/nmaas/orchestration/jobs/DomainCreationJob.java
index 3d5d751dc1c2fdf6e29f30d5c7f278305e43e37a..aaf0fd167f24d7bc422ba0cef7bf4724457e79db 100644
--- a/src/main/java/net/geant/nmaas/orchestration/jobs/DomainCreationJob.java
+++ b/src/main/java/net/geant/nmaas/orchestration/jobs/DomainCreationJob.java
@@ -45,9 +45,7 @@ public class DomainCreationJob extends WebhookJob {
             }
 
             Domain domain = domainService.findDomain(domainId).orElseThrow(() -> new MissingElementException(String.format("Domain with id: %d cannot be found", domainId)));
-            DomainView view = modelMapper.map(domain, DomainView.class);
-
-            callWebhook(webhook, view);
+            callWebhook(webhook, modelMapper.map(domain, DomainView.class));
         } catch (GeneralSecurityException e) {
             log.error("Failed to decrypt webhook with id {}", webhookId);
             throw new JobExecutionException("Failed webhook decryption");
diff --git a/src/main/java/net/geant/nmaas/orchestration/jobs/UserDomainAssignmentJob.java b/src/main/java/net/geant/nmaas/orchestration/jobs/UserDomainAssignmentJob.java
new file mode 100644
index 0000000000000000000000000000000000000000..eaf449f99de8e6843d72af3dd4e1226775692e4d
--- /dev/null
+++ b/src/main/java/net/geant/nmaas/orchestration/jobs/UserDomainAssignmentJob.java
@@ -0,0 +1,72 @@
+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.DomainView;
+import net.geant.nmaas.portal.api.domain.UserDomainAssignmentWebhookDto;
+import net.geant.nmaas.portal.api.domain.UserView;
+import net.geant.nmaas.portal.api.domain.WebhookEventDto;
+import net.geant.nmaas.portal.api.exceptions.MissingElementException;
+import net.geant.nmaas.portal.persistent.entity.Domain;
+import net.geant.nmaas.portal.persistent.entity.Role;
+import net.geant.nmaas.portal.persistent.entity.User;
+import net.geant.nmaas.portal.persistent.entity.WebhookEventType;
+import net.geant.nmaas.portal.service.DomainService;
+import net.geant.nmaas.portal.service.UserService;
+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 UserDomainAssignmentJob extends WebhookJob {
+
+    private final DomainService domainService;
+    private final UserService userService;
+
+    @Autowired
+    public UserDomainAssignmentJob(RestClient restClient, WebhookEventService webhookEventService, ModelMapper modelMapper, DomainService domainService, UserService userService) {
+        super(restClient, webhookEventService, modelMapper);
+        this.domainService = domainService;
+        this.userService = userService;
+    }
+
+    @Override
+    public void execute(JobExecutionContext context) throws JobExecutionException {
+        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
+        Long webhookId = dataMap.getLong("webhookId");
+        Long domainId = dataMap.getLong("domainId");
+        Long userId = dataMap.getLong("userId");
+        Role role = Role.valueOf(dataMap.getString("role"));
+        String action = dataMap.getString("action");
+
+        try {
+            WebhookEventDto webhook = webhookEventService.getById(webhookId);
+            if (!WebhookEventType.USER_ASSIGNMENT.equals(webhook.getEventType())) {
+                log.warn("Webhook's event type with id {} has been updated. UserDomainAssignmentJob is abandoned", webhookId);
+                return;
+            }
+            Domain domain = domainService.findDomain(domainId).orElseThrow(() -> new MissingElementException(String.format("Domain with id: %d cannot be found", domainId)));
+            User user = userService.findById(userId).orElseThrow(() -> new MissingElementException(String.format("User with id: %d cannot be found", userId)));
+
+            UserDomainAssignmentWebhookDto dto = new UserDomainAssignmentWebhookDto(modelMapper.map(user, UserView.class), modelMapper.map(domain, DomainView.class), role, action);
+            callWebhook(webhook, dto);
+        } catch (GeneralSecurityException e) {
+            log.error("Failed to decrypt webhook with id {}", webhookId);
+            throw new JobExecutionException("Failed webhook decryption");
+        } catch (MissingElementException e) {
+            log.warn(e.getMessage() + " UserDomainAssignmentJob is abandoned");
+        } catch (WebServiceCommunicationException e) {
+            log.error("Failed to communicate with external system for the webhoook of assignment of the user with id {} in the domain with id {}", userId, domainId);
+            throw new JobExecutionException("Failed communication with external system");
+        }
+    }
+}
+
diff --git a/src/main/java/net/geant/nmaas/portal/api/domain/UserDomainAssignmentWebhookDto.java b/src/main/java/net/geant/nmaas/portal/api/domain/UserDomainAssignmentWebhookDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..a414eda477cfa75da8908c9077b0a90b9a9a77cd
--- /dev/null
+++ b/src/main/java/net/geant/nmaas/portal/api/domain/UserDomainAssignmentWebhookDto.java
@@ -0,0 +1,17 @@
+package net.geant.nmaas.portal.api.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import net.geant.nmaas.portal.persistent.entity.Role;
+
+@AllArgsConstructor
+@Getter
+@Setter
+public class UserDomainAssignmentWebhookDto {
+
+    private UserView user;
+    private DomainView domain;
+    private Role role;
+    private String action;
+}
diff --git a/src/main/java/net/geant/nmaas/portal/api/user/UsersController.java b/src/main/java/net/geant/nmaas/portal/api/user/UsersController.java
index f2a6103f6e605ee2732e5afebaa42348d8e0a919..d7b8e2ccdb1783331a8d6144a1822662e477c137 100644
--- a/src/main/java/net/geant/nmaas/portal/api/user/UsersController.java
+++ b/src/main/java/net/geant/nmaas/portal/api/user/UsersController.java
@@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j;
 import net.geant.nmaas.notifications.MailAttributes;
 import net.geant.nmaas.notifications.NotificationEvent;
 import net.geant.nmaas.notifications.templates.MailType;
+import net.geant.nmaas.orchestration.jobs.UserDomainAssignmentJob;
 import net.geant.nmaas.portal.api.domain.PasswordChange;
 import net.geant.nmaas.portal.api.domain.PasswordReset;
 import net.geant.nmaas.portal.api.domain.UserBase;
@@ -22,11 +23,14 @@ import net.geant.nmaas.portal.persistent.entity.Domain;
 import net.geant.nmaas.portal.persistent.entity.Role;
 import net.geant.nmaas.portal.persistent.entity.User;
 import net.geant.nmaas.portal.persistent.entity.UserRole;
+import net.geant.nmaas.portal.persistent.entity.WebhookEventType;
+import net.geant.nmaas.portal.persistent.repositories.WebhookEventRepository;
 import net.geant.nmaas.portal.persistent.results.UserLoginDate;
 import net.geant.nmaas.portal.service.ApplicationInstanceService;
 import net.geant.nmaas.portal.service.DomainService;
 import net.geant.nmaas.portal.service.UserLoginRegisterService;
 import net.geant.nmaas.portal.service.UserService;
+import net.geant.nmaas.scheduling.ScheduleManager;
 import net.geant.nmaas.utils.captcha.ValidateCaptcha;
 import org.apache.commons.lang3.StringUtils;
 import org.modelmapper.ModelMapper;
@@ -52,6 +56,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.security.Principal;
+import java.time.LocalDateTime;
 import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -100,6 +105,8 @@ public class UsersController {
     private final UserLoginRegisterService userLoginService;
 
     private final ApplicationInstanceService instanceService;
+    private final WebhookEventRepository webhookEventRepository;
+    private final ScheduleManager scheduleManager;
 
     @Autowired
     public UsersController(UserService userService,
@@ -109,7 +116,9 @@ public class UsersController {
                            JWTTokenService jwtTokenService,
                            ApplicationEventPublisher eventPublisher,
                            UserLoginRegisterService userLoginService,
-                           ApplicationInstanceService instanceService) {
+                           ApplicationInstanceService instanceService,
+                           WebhookEventRepository webhookEventRepository,
+                           ScheduleManager scheduleManager) {
         this.userService = userService;
         this.domainService = domainService;
         this.modelMapper = modelMapper;
@@ -118,6 +127,8 @@ public class UsersController {
         this.eventPublisher = eventPublisher;
         this.userLoginService = userLoginService;
         this.instanceService = instanceService;
+        this.webhookEventRepository = webhookEventRepository;
+        this.scheduleManager = scheduleManager;
     }
 
     @GetMapping("/users")
@@ -508,6 +519,9 @@ public class UsersController {
 
         try {
             domainService.addMemberRole(domain.getId(), user.getId(), role);
+            if (!domain.equals(globalDomain)){
+                webhookEventRepository.findIdByEventType(WebhookEventType.USER_ASSIGNMENT).forEach(id -> scheduleManager.createOneTimeJob(UserDomainAssignmentJob.class, "UserDomainAssignmentJobCreate_" + id + "_user" + user.getId()+ "_domain" + domain.getId()+"_" + LocalDateTime.now(), Map.of("webhookId", id, "domainId", domain.getId(), "userId", user.getId(), "role", role.name(), "action", "create")));
+            }
 
             final User adminUser = userService.findByUsername(principal.getName()).orElseThrow(() -> new ObjectNotFoundException(USER_NOT_FOUND_ERROR_MESSAGE));
             final String adminRoles = getRoleAsString(adminUser.getRoles());
@@ -541,6 +555,10 @@ public class UsersController {
             domainService.removeMemberRole(domain.getId(), user.getId(), role);
             final User adminUser = userService.findByUsername(principal.getName()).orElseThrow(() -> new ObjectNotFoundException(USER_NOT_FOUND_ERROR_MESSAGE));
             final String adminRoles = getRoleAsString(adminUser.getRoles());
+            final Domain globalDomain = domainService.getGlobalDomain().orElse(null);
+            if (!domain.equals(globalDomain)){
+                webhookEventRepository.findIdByEventType(WebhookEventType.USER_ASSIGNMENT).forEach(id -> scheduleManager.createOneTimeJob(UserDomainAssignmentJob.class, "UserDomainAssignmentJobDelete_" + id + "_user" + user.getId()+ "_domain" + domain.getId()+"_" + LocalDateTime.now(), Map.of("webhookId", id, "domainId", domain.getId(), "userId", user.getId(), "role", role.name(), "action", "delete")));
+            }
 
             log.info(String.format("User [%s] with role [%s] removed role [%s] of user name [%s] in domain [%d].",
                     principal.getName(),
diff --git a/src/test/java/net/geant/nmaas/portal/api/market/UsersControllerTest.java b/src/test/java/net/geant/nmaas/portal/api/market/UsersControllerTest.java
index 4b70031a859db6b376533e8fc2289470f652365d..08ee1aab9e26f09fd7e0f61c35a7c3a9b75b66c8 100644
--- a/src/test/java/net/geant/nmaas/portal/api/market/UsersControllerTest.java
+++ b/src/test/java/net/geant/nmaas/portal/api/market/UsersControllerTest.java
@@ -1,6 +1,8 @@
 package net.geant.nmaas.portal.api.market;
 
 import com.google.common.collect.ImmutableSet;
+import net.geant.nmaas.orchestration.jobs.DomainCreationJob;
+import net.geant.nmaas.orchestration.jobs.UserDomainAssignmentJob;
 import net.geant.nmaas.portal.api.domain.PasswordChange;
 import net.geant.nmaas.portal.api.domain.UserRequest;
 import net.geant.nmaas.portal.api.domain.UserRoleView;
@@ -14,13 +16,23 @@ import net.geant.nmaas.portal.exceptions.ObjectNotFoundException;
 import net.geant.nmaas.portal.persistent.entity.Domain;
 import net.geant.nmaas.portal.persistent.entity.Role;
 import net.geant.nmaas.portal.persistent.entity.User;
+import net.geant.nmaas.portal.persistent.entity.WebhookEvent;
+import net.geant.nmaas.portal.persistent.entity.WebhookEventType;
+import net.geant.nmaas.portal.persistent.repositories.WebhookEventRepository;
 import net.geant.nmaas.portal.service.ApplicationInstanceService;
 import net.geant.nmaas.portal.service.DomainService;
 import net.geant.nmaas.portal.service.UserLoginRegisterService;
 import net.geant.nmaas.portal.service.UserService;
+import net.geant.nmaas.scheduling.ScheduleManager;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.mockito.internal.verification.VerificationModeFactory;
 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 org.springframework.context.ApplicationEventPublisher;
 import org.springframework.security.crypto.password.PasswordEncoder;
 
@@ -30,15 +42,19 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Stream;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
+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.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 
 public class UsersControllerTest {
@@ -69,9 +85,15 @@ public class UsersControllerTest {
 
 	private final ApplicationInstanceService instanceService = mock(ApplicationInstanceService.class);
 
+	WebhookEventRepository webhookEventRepository = mock(WebhookEventRepository.class);
+	Scheduler scheduler = mock(Scheduler.class);
+	ListenerManager listenerManager = mock(ListenerManager.class);
+	ScheduleManager scheduleManager;
+
 	@BeforeEach
 	public void setup(){
-		usersController = new UsersController(userService, domainService, modelMapper, passwordEncoder, jwtTokenService, eventPublisher, userLoginService, instanceService);
+		scheduleManager = new ScheduleManager(scheduler);
+		usersController = new UsersController(userService, domainService, modelMapper, passwordEncoder, jwtTokenService, eventPublisher, userLoginService, instanceService, webhookEventRepository, scheduleManager);
 		User tester = new User("tester", true, "test123", DOMAIN, Role.ROLE_USER);
 		tester.setId(1L);
 		User admin = new User("testadmin", true, "testadmin123", DOMAIN, Role.ROLE_SYSTEM_ADMIN);
@@ -329,12 +351,31 @@ public class UsersControllerTest {
 	}
 
 	@Test
-	public void shouldAddUserRoleToCustomDomain(){
+	public void shouldAddUserRoleToCustomDomain() throws SchedulerException {
 		UserRoleView userRole = new UserRoleView();
 		userRole.setDomainId(DOMAIN.getId());
 		userRole.setRole(Role.ROLE_USER);
+		// Setup webhook event
+		WebhookEvent webhookEvent = new WebhookEvent(1L, "webhook", "https://example.com/webhook", WebhookEventType.USER_ASSIGNMENT, null, null);
+		when(webhookEventRepository.findIdByEventType(WebhookEventType.USER_ASSIGNMENT))
+				.thenReturn(Stream.of(1L));
+		when(webhookEventRepository.findById(1L))
+				.thenReturn(Optional.of(webhookEvent));
+		when(scheduler.getListenerManager()).thenReturn(listenerManager);
+		doNothing().when(listenerManager).addJobListener(any(JobListener.class), any(Matcher.class));
+
 		usersController.addUserRole(DOMAIN.getId(), userList.get(0).getId(), userRole, principal);
 		verify(domainService, times(1)).addMemberRole(DOMAIN.getId(), userList.get(0).getId(), userRole.getRole());
+		// Verify webhook job was scheduled
+		verify(scheduler, VerificationModeFactory.times(1)).scheduleJob(
+				argThat(jobDetail ->
+						jobDetail.getKey().getName().startsWith("UserDomainAssignmentJobCreate_1_user"+userList.get(0).getId()+"_domain2") &&
+								jobDetail.getJobClass().equals(UserDomainAssignmentJob.class)
+				),
+				argThat(trigger ->
+						trigger.getKey().getName().startsWith("UserDomainAssignmentJobCreate_1_user"+userList.get(0).getId()+"_domain2")
+				)
+		);
 	}
 
 	@Test
@@ -345,6 +386,8 @@ public class UsersControllerTest {
 		when(domainService.findDomain(GLOBAL_DOMAIN.getId())).thenReturn(Optional.of(GLOBAL_DOMAIN));
 		usersController.addUserRole(GLOBAL_DOMAIN.getId(), userList.get(0).getId(), userRole, principal);
 		verify(domainService, times(1)).addMemberRole(GLOBAL_DOMAIN.getId(), userList.get(0).getId(), userRole.getRole());
+
+		verifyNoInteractions(scheduler);
 	}
 
 	@Test
@@ -396,10 +439,29 @@ public class UsersControllerTest {
 	}
 
 	@Test
-	public void shouldRemoveUserRole(){
+	public void shouldRemoveUserRole() throws SchedulerException {
 		String userRole = "ROLE_SYSTEM_ADMIN";
+		// Setup webhook event
+		WebhookEvent webhookEvent = new WebhookEvent(1L, "webhook", "https://example.com/webhook", WebhookEventType.USER_ASSIGNMENT, null, null);
+		when(webhookEventRepository.findIdByEventType(WebhookEventType.USER_ASSIGNMENT))
+				.thenReturn(Stream.of(1L));
+		when(webhookEventRepository.findById(1L))
+				.thenReturn(Optional.of(webhookEvent));
+		when(scheduler.getListenerManager()).thenReturn(listenerManager);
+		doNothing().when(listenerManager).addJobListener(any(JobListener.class), any(Matcher.class));
+
 		usersController.removeUserRole(DOMAIN.getId(), userList.get(0).getId(), userRole, principal);
 		verify(domainService, times(1)).removeMemberRole(DOMAIN.getId(), userList.get(0).getId(), Role.ROLE_SYSTEM_ADMIN);
+		// Verify webhook job was scheduled
+		verify(scheduler, VerificationModeFactory.times(1)).scheduleJob(
+				argThat(jobDetail ->
+						jobDetail.getKey().getName().startsWith("UserDomainAssignmentJobDelete_1_user"+userList.get(0).getId()+"_domain2") &&
+								jobDetail.getJobClass().equals(UserDomainAssignmentJob.class)
+				),
+				argThat(trigger ->
+						trigger.getKey().getName().startsWith("UserDomainAssignmentJobDelete_1_user"+userList.get(0).getId()+"_domain2")
+				)
+		);
 	}
 
 	@Test