diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php
index dcf18e0e53b7ecd893c040ec8964199cafce39d7..d2cba549846bcd1527ddf5bc0155115a7634a739 100644
--- a/apps/provisioning_api/appinfo/routes.php
+++ b/apps/provisioning_api/appinfo/routes.php
@@ -37,7 +37,7 @@ $users = new \OCA\Provisioning_API\Users(
 	\OC::$server->getLogger()
 );
 API::register('get', '/cloud/users', [$users, 'getUsers'], 'provisioning_api', API::SUBADMIN_AUTH);
-API::register('post', '/cloud/users', [$users, 'addUser'], 'provisioning_api', API::ADMIN_AUTH);
+API::register('post', '/cloud/users', [$users, 'addUser'], 'provisioning_api', API::SUBADMIN_AUTH);
 API::register('get', '/cloud/users/{userid}', [$users, 'getUser'], 'provisioning_api', API::USER_AUTH);
 API::register('put', '/cloud/users/{userid}', [$users, 'editUser'], 'provisioning_api', API::USER_AUTH);
 API::register('delete', '/cloud/users/{userid}', [$users, 'deleteUser'], 'provisioning_api', API::SUBADMIN_AUTH);
diff --git a/apps/provisioning_api/lib/users.php b/apps/provisioning_api/lib/users.php
index 304fe901cfd665ae49926d241a46a1bc9e34807b..a2568425d0fbb627bac5611b50e8e55abc933a7c 100644
--- a/apps/provisioning_api/lib/users.php
+++ b/apps/provisioning_api/lib/users.php
@@ -117,19 +117,50 @@ class Users {
 	public function addUser() {
 		$userId = isset($_POST['userid']) ? $_POST['userid'] : null;
 		$password = isset($_POST['password']) ? $_POST['password'] : null;
+		$groups = isset($_POST['groups']) ? $_POST['groups'] : null;
+		$user = $this->userSession->getUser();
+		$isAdmin = $this->groupManager->isAdmin($user->getUID());
+		$subAdminManager = $this->groupManager->getSubAdmin();
+
+		if (!$isAdmin && !$subAdminManager->isSubAdmin($user)) {
+			return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+		}
+
 		if($this->userManager->userExists($userId)) {
 			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
 			return new OC_OCS_Result(null, 102, 'User already exists');
+		}
+
+		if(is_array($groups)) {
+			foreach ($groups as $group) {
+				if(!$this->groupManager->groupExists($group)){
+					return new OC_OCS_Result(null, 104, 'group '.$group.' does not exist');
+				}
+				if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
+					return new OC_OCS_Result(null, 105, 'insufficient privileges for group '. $group);
+				}
+			}
 		} else {
-			try {
-				$this->userManager->createUser($userId, $password);
-				$this->logger->info('Successful addUser call with userid: '.$_POST['userid'], ['app' => 'ocs_api']);
-				return new OC_OCS_Result(null, 100);
-			} catch (\Exception $e) {
-				$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
-				return new OC_OCS_Result(null, 101, 'Bad request');
+			if(!$isAdmin) {
+				return new OC_OCS_Result(null, 106, 'no group specified (required for subadmins)');
 			}
 		}
+		
+		try {
+			$newUser = $this->userManager->createUser($userId, $password);
+			$this->logger->info('Successful addUser call with userid: '.$userId, ['app' => 'ocs_api']);
+
+			if (is_array($groups)) {
+				foreach ($groups as $group) {
+					$this->groupManager->get($group)->addUser($newUser);
+					$this->logger->info('Added userid '.$userId.' to group '.$group, ['app' => 'ocs_api']);
+				}
+			}
+			return new OC_OCS_Result(null, 100);
+		} catch (\Exception $e) {
+			$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
+			return new OC_OCS_Result(null, 101, 'Bad request');
+		}
 	}
 
 	/**
diff --git a/apps/provisioning_api/tests/userstest.php b/apps/provisioning_api/tests/userstest.php
index ba4ed8a2e2f93ce2d2ff2d374f2f3948c591e878..63180eb3472a8c992bbacdb6e0ae2856ce2d9a78 100644
--- a/apps/provisioning_api/tests/userstest.php
+++ b/apps/provisioning_api/tests/userstest.php
@@ -218,11 +218,95 @@ class UsersTest extends OriginalTest {
 			->expects($this->once())
 			->method('error')
 			->with('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('adminUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('adminUser')
+			->willReturn(true);
 
 		$expected = new \OC_OCS_Result(null, 102, 'User already exists');
 		$this->assertEquals($expected, $this->api->addUser());
 	}
 
+	public function testAddUserNonExistingGroup() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['groups'] = ['NonExistingGroup'];
+		$this->userManager
+			->expects($this->once())
+			->method('userExists')
+			->with('NewUser')
+			->willReturn(false);
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('adminUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('adminUser')
+			->willReturn(true);
+		$this->groupManager
+			->expects($this->once())
+			->method('groupExists')
+			->with('NonExistingGroup')
+			->willReturn(false);
+
+		$expected = new \OC_OCS_Result(null, 104, 'group NonExistingGroup does not exist');
+		$this->assertEquals($expected, $this->api->addUser());
+	}
+
+	public function testAddUserExistingGroupNonExistingGroup() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['groups'] = ['ExistingGroup', 'NonExistingGroup'];
+		$this->userManager
+			->expects($this->once())
+			->method('userExists')
+			->with('NewUser')
+			->willReturn(false);
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('adminUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('adminUser')
+			->willReturn(true);
+		$this->groupManager
+			->expects($this->exactly(2))
+			->method('groupExists')
+			->withConsecutive(
+				['ExistingGroup'],
+				['NonExistingGroup']
+			)
+			->will($this->returnValueMap([
+				['ExistingGroup', true],
+				['NonExistingGroup', false]
+			]));
+
+		$expected = new \OC_OCS_Result(null, 104, 'group NonExistingGroup does not exist');
+		$this->assertEquals($expected, $this->api->addUser());
+	}
+
 	public function testAddUserSuccessful() {
 		$_POST['userid'] = 'NewUser';
 		$_POST['password'] = 'PasswordOfTheNewUser';
@@ -239,6 +323,76 @@ class UsersTest extends OriginalTest {
 			->expects($this->once())
 			->method('info')
 			->with('Successful addUser call with userid: NewUser', ['app' => 'ocs_api']);
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('adminUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('adminUser')
+			->willReturn(true);
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->addUser());
+	}
+
+	public function testAddUserExistingGroup() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['password'] = 'PasswordOfTheNewUser';
+		$_POST['groups'] = ['ExistingGroup'];
+		$this->userManager
+			->expects($this->once())
+			->method('userExists')
+			->with('NewUser')
+			->willReturn(false);
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('adminUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('adminUser')
+			->willReturn(true);
+		$this->groupManager
+			->expects($this->once())
+			->method('groupExists')
+			->with('ExistingGroup')
+			->willReturn(true);
+		$user = $this->getMock('\OCP\IUser');
+		$this->userManager
+			->expects($this->once())
+			->method('createUser')
+			->with('NewUser', 'PasswordOfTheNewUser')
+			->willReturn($user);
+		$group = $this->getMock('\OCP\IGroup');
+		$group
+			->expects($this->once())
+			->method('addUser')
+			->with($user);
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingGroup')
+			->willReturn($group);
+		$this->logger
+			->expects($this->exactly(2))
+			->method('info')
+			->withConsecutive(
+				['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']],
+				['Added userid NewUser to group ExistingGroup', ['app' => 'ocs_api']]
+			);
 
 		$expected = new \OC_OCS_Result(null, 100);
 		$this->assertEquals($expected, $this->api->addUser());
@@ -261,11 +415,238 @@ class UsersTest extends OriginalTest {
 			->expects($this->once())
 			->method('error')
 			->with('Failed addUser attempt with exception: User backend not found.', ['app' => 'ocs_api']);
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('adminUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('adminUser')
+			->willReturn(true);
 
 		$expected = new \OC_OCS_Result(null, 101, 'Bad request');
 		$this->assertEquals($expected, $this->api->addUser());
 	}
 
+	public function testAddUserAsRegularUser() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['password'] = 'PasswordOfTheNewUser';
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('regularUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('regularUser')
+			->willReturn(false);
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdmin')
+			->with($loggedInUser)
+			->willReturn(false);
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->with()
+			->willReturn($subAdminManager);
+
+		$expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+		$this->assertEquals($expected, $this->api->addUser());	
+	}
+
+	public function testAddUserAsSubAdminNoGroup() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['password'] = 'PasswordOfTheNewUser';
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('regularUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('regularUser')
+			->willReturn(false);
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdmin')
+			->with($loggedInUser)
+			->willReturn(true);
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->with()
+			->willReturn($subAdminManager);
+
+		$expected = new \OC_OCS_Result(null, 106, 'no group specified (required for subadmins)');
+		$this->assertEquals($expected, $this->api->addUser());	
+	}
+
+	public function testAddUserAsSubAdminValidGroupNotSubAdmin() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['password'] = 'PasswordOfTheNewUser';
+		$_POST['groups'] = ['ExistingGroup'];
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('regularUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('regularUser')
+			->willReturn(false);
+		$existingGroup = $this->getMock('\OCP\IGroup');
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingGroup')
+			->willReturn($existingGroup);
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdmin')
+			->with($loggedInUser)
+			->willReturn(true);
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdminOfGroup')
+			->with($loggedInUser, $existingGroup)
+			->wilLReturn(false);
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->with()
+			->willReturn($subAdminManager);
+		$this->groupManager
+			->expects($this->once())
+			->method('groupExists')
+			->with('ExistingGroup')
+			->willReturn(true);
+
+		$expected = new \OC_OCS_Result(null, 105, 'insufficient privileges for group ExistingGroup');
+		$this->assertEquals($expected, $this->api->addUser());	
+	}
+
+	public function testAddUserAsSubAdminExistingGroups() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['password'] = 'PasswordOfTheNewUser';
+		$_POST['groups'] = ['ExistingGroup1', 'ExistingGroup2'];
+		$this->userManager
+			->expects($this->once())
+			->method('userExists')
+			->with('NewUser')
+			->willReturn(false);
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('subAdminUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subAdminUser')
+			->willReturn(false);
+		$this->groupManager
+			->expects($this->exactly(2))
+			->method('groupExists')
+			->withConsecutive(
+				['ExistingGroup1'],
+				['ExistingGroup2']
+			)
+			->willReturn(true);
+		$user = $this->getMock('\OCP\IUser');
+		$this->userManager
+			->expects($this->once())
+			->method('createUser')
+			->with('NewUser', 'PasswordOfTheNewUser')
+			->willReturn($user);
+		$existingGroup1 = $this->getMock('\OCP\IGroup');
+		$existingGroup2 = $this->getMock('\OCP\IGroup');
+		$existingGroup1
+			->expects($this->once())
+			->method('addUser')
+			->with($user);
+		$existingGroup2
+			->expects($this->once())
+			->method('addUser')
+			->with($user);
+		$this->groupManager
+			->expects($this->exactly(4))
+			->method('get')
+			->withConsecutive(
+				['ExistingGroup1'],
+				['ExistingGroup2'],
+				['ExistingGroup1'],
+				['ExistingGroup2']
+			)
+			->will($this->returnValueMap([
+				['ExistingGroup1', $existingGroup1],
+				['ExistingGroup2', $existingGroup2]
+			]));
+		$this->logger
+			->expects($this->exactly(3))
+			->method('info')
+			->withConsecutive(
+				['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']],
+				['Added userid NewUser to group ExistingGroup1', ['app' => 'ocs_api']],
+				['Added userid NewUser to group ExistingGroup2', ['app' => 'ocs_api']]
+			);
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->willReturn($subAdminManager);
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdmin')
+			->with($loggedInUser)
+			->willReturn(true);
+		$subAdminManager
+			->expects($this->exactly(2))
+			->method('isSubAdminOfGroup')
+			->withConsecutive(
+				[$loggedInUser, $existingGroup1],
+				[$loggedInUser, $existingGroup2]
+			)
+			->wilLReturn(true);
+
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->addUser());
+	}
+
+
 	public function testGetUserNotLoggedIn() {
 		$this->userSession
 			->expects($this->once())