diff --git a/gms-client/gms-client-lib/pom.xml b/gms-client/gms-client-lib/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bbaa736ece4a88237260bb725dda6a6dcf8499d9
--- /dev/null
+++ b/gms-client/gms-client-lib/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>it.inaf.ia2</groupId>
+    <artifactId>gms-client-lib</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <spring.version>5.1.8.RELEASE</spring.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..b9ddaf8b885841e1562f2c7ba1a611fee697f3e3
--- /dev/null
+++ b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java
@@ -0,0 +1,112 @@
+package it.inaf.ia2.gms.client;
+
+import it.inaf.ia2.gms.client.model.Group;
+import it.inaf.ia2.gms.client.model.Member;
+import it.inaf.ia2.gms.client.model.Permission;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+public class GmsClient {
+
+    private static final String WS = "ws";
+
+    private final String baseUrl;
+    private final RestTemplate restTemplate;
+
+    public GmsClient(String baseUrl, String clientId, String clientSecret) {
+        this.baseUrl = baseUrl;
+        restTemplate = new RestTemplate();
+    }
+
+    public Group createGroup(List<String> names) {
+
+        String url = UriComponentsBuilder.fromHttpUrl(baseUrl)
+                .pathSegment(WS, "group")
+                .toUriString();
+
+        HttpEntity<List<String>> httpEntity = new HttpEntity<>(names);
+
+        return restTemplate.exchange(url, HttpMethod.POST, httpEntity, Group.class).getBody();
+    }
+
+    public void deleteGroupByPath(List<String> names) {
+
+        String url = UriComponentsBuilder.fromHttpUrl(baseUrl)
+                .pathSegment(WS, "group")
+                .queryParam("names", names)
+                .toUriString();
+
+        restTemplate.delete(url);
+    }
+
+    public Member addMember(List<String> names, String userId) {
+
+        String url = UriComponentsBuilder.fromHttpUrl(baseUrl)
+                .pathSegment(WS, "member")
+                .toUriString();
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("names", names);
+        params.put("userId", userId);
+        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
+
+        return restTemplate.exchange(url, HttpMethod.POST, httpEntity, Member.class).getBody();
+    }
+
+    public void removeMember(List<String> names, String userId) {
+
+        String url = UriComponentsBuilder.fromHttpUrl(baseUrl)
+                .pathSegment(WS, "member")
+                .queryParam("names", names)
+                .queryParam("userId", userId)
+                .toUriString();
+
+        restTemplate.delete(url);
+    }
+
+    public Permission addPermission(List<String> names, String userId, String permission) {
+
+        String url = UriComponentsBuilder.fromHttpUrl(baseUrl)
+                .pathSegment(WS, "permission")
+                .toUriString();
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("names", names);
+        params.put("userId", userId);
+        params.put("permission", permission);
+        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
+
+        return restTemplate.exchange(url, HttpMethod.POST, httpEntity, Permission.class).getBody();
+    }
+
+    public void deletePermission(List<String> names, String userId, String permission) {
+
+        String url = UriComponentsBuilder.fromHttpUrl(baseUrl)
+                .pathSegment(WS, "permission")
+                .queryParam("names", names)
+                .queryParam("userId", userId)
+                .queryParam("permission", permission)
+                .toUriString();
+
+        restTemplate.delete(url);
+    }
+
+    public void prepareToJoin(String fromUserId, String toUserId) {
+
+        String url = UriComponentsBuilder.fromHttpUrl(baseUrl)
+                .pathSegment(WS, "prepare-join")
+                .toUriString();
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("fromUserId", fromUserId);
+        params.put("toUserId", toUserId);
+        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
+
+        restTemplate.exchange(url, HttpMethod.POST, httpEntity, Void.class);
+    }
+}
diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Group.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Group.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0b95fdb5190aaf1e1817927944c8b910661283d
--- /dev/null
+++ b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Group.java
@@ -0,0 +1,41 @@
+package it.inaf.ia2.gms.client.model;
+
+public class Group {
+
+    private String id;
+    private String name;
+    private String path;
+    private String parentPath;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public String getParentPath() {
+        return parentPath;
+    }
+
+    public void setParentPath(String parentPath) {
+        this.parentPath = parentPath;
+    }
+}
diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Member.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Member.java
new file mode 100644
index 0000000000000000000000000000000000000000..37b0096c79c7e455f6f65937dcb2d8aa629964e5
--- /dev/null
+++ b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Member.java
@@ -0,0 +1,23 @@
+package it.inaf.ia2.gms.client.model;
+
+public class Member {
+
+    private String groupId;
+    private String userId;
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+}
diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Permission.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Permission.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb809c4ee8a4bfe12039c24caf6b2880a2bf0636
--- /dev/null
+++ b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Permission.java
@@ -0,0 +1,32 @@
+package it.inaf.ia2.gms.client.model;
+
+public class Permission {
+
+    private String groupId;
+    private String userId;
+    private String permission;
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getPermission() {
+        return permission;
+    }
+
+    public void setPermission(String permission) {
+        this.permission = permission;
+    }
+}
diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/WebServiceController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/WebServiceController.java
index f71e4e35433f8ae9eb2b79c4c186f99542b84641..04c067cb2a92882d0fd2cd83f8ddfdc58625a1b4 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/controller/WebServiceController.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/controller/WebServiceController.java
@@ -1,6 +1,7 @@
 package it.inaf.ia2.gms.controller;
 
 import it.inaf.ia2.gms.exception.BadRequestException;
+import it.inaf.ia2.gms.model.AddMemberWsRequest;
 import it.inaf.ia2.gms.model.AddPermissionWsRequest;
 import it.inaf.ia2.gms.model.Permission;
 import it.inaf.ia2.gms.model.PrepareToJoinRequest;
@@ -70,8 +71,12 @@ public class WebServiceController {
     }
 
     @PostMapping(value = "/member", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
-    public ResponseEntity<MembershipEntity> addMember(@RequestBody MembershipEntity request) {
-        MembershipEntity membership = membersService.addMember(request.getGroupId(), request.getUserId());
+    public ResponseEntity<MembershipEntity> addMember(@RequestBody AddMemberWsRequest request) {
+
+        GroupEntity group = getGroupByNames(request.getNames());
+
+        MembershipEntity membership = membersService.addMember(group.getId(), request.getUserId());
+
         return new ResponseEntity<>(membership, HttpStatus.CREATED);
     }
 
diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/AddMemberWsRequest.java b/gms/src/main/java/it/inaf/ia2/gms/model/AddMemberWsRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf698046f6a6c08b040a2ded9546f83aa6052069
--- /dev/null
+++ b/gms/src/main/java/it/inaf/ia2/gms/model/AddMemberWsRequest.java
@@ -0,0 +1,25 @@
+package it.inaf.ia2.gms.model;
+
+import java.util.List;
+
+public class AddMemberWsRequest {
+
+    private List<String> names;
+    private String userId;
+
+    public List<String> getNames() {
+        return names;
+    }
+
+    public void setNames(List<String> names) {
+        this.names = names;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+}
diff --git a/gms/src/test/java/it/inaf/ia2/gms/controller/WebServiceControllerTest.java b/gms/src/test/java/it/inaf/ia2/gms/controller/WebServiceControllerTest.java
index fe53d1fa033b582b5163b5d2f59c8b33195cea79..573b5f51cd29d462b7e129b8825f9d90d395592c 100644
--- a/gms/src/test/java/it/inaf/ia2/gms/controller/WebServiceControllerTest.java
+++ b/gms/src/test/java/it/inaf/ia2/gms/controller/WebServiceControllerTest.java
@@ -1,6 +1,7 @@
 package it.inaf.ia2.gms.controller;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import it.inaf.ia2.gms.model.AddMemberWsRequest;
 import it.inaf.ia2.gms.model.AddPermissionWsRequest;
 import it.inaf.ia2.gms.model.Permission;
 import it.inaf.ia2.gms.model.PrepareToJoinRequest;
@@ -108,19 +109,29 @@ public class WebServiceControllerTest {
     @Test
     public void testAddMember() throws Exception {
 
+        List<String> names = getNames("LBT", "INAF");
+
+        GroupEntity inaf = getInafGroup();
+
+        when(groupsService.findGroupByNames(names)).thenReturn(Optional.of(inaf));
+
+        AddMemberWsRequest request = new AddMemberWsRequest();
+        request.setNames(names);
+        request.setUserId("user_id");
+
         MembershipEntity membership = new MembershipEntity();
-        membership.setGroupId("group_id");
-        membership.setUserId("user_id");
+        membership.setGroupId(inaf.getId());
+        membership.setUserId(request.getUserId());
 
-        when(membersService.addMember(eq("group_id"), eq("user_id")))
+        when(membersService.addMember(eq(inaf.getId()), eq(request.getUserId())))
                 .thenReturn(membership);
 
         mockMvc.perform(post("/ws/member")
-                .content(mapper.writeValueAsString(membership))
+                .content(mapper.writeValueAsString(request))
                 .contentType(MediaType.APPLICATION_JSON_UTF8))
                 .andExpect(status().isCreated())
-                .andExpect(jsonPath("$.groupId", is("group_id")))
-                .andExpect(jsonPath("$.userId", is("user_id")));
+                .andExpect(jsonPath("$.groupId", is(inaf.getId())))
+                .andExpect(jsonPath("$.userId", is(request.getUserId())));
     }
 
     @Test