diff --git a/server/ms_creategroup.sas b/server/ms_creategroup.sas
new file mode 100644
index 0000000..26bf6a5
--- /dev/null
+++ b/server/ms_creategroup.sas
@@ -0,0 +1,139 @@
+/**
+ @file
+ @brief Creates a group on SASjs Server
+ @details Creates a group on SASjs Server with the following attributes:
+
+ @li name
+ @li description
+ @li isActive
+
+ Examples:
+
+ %ms_creategroup(mynewgroup)
+
+ %ms_creategroup(mynewergroup, desc=The group description)
+
+ @param [in] groupname The group name to create. No spaces or special chars.
+ @param [in] desc= (0) If no description provided, group name will be used.
+ @param [in] isactive= (true) Set to false to create an inactive group.
+ @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
+ @param [out] outds= (work.ms_creategroup) This output dataset will contain the
+ values from the JSON response (such as the id of the new group)
+|DESCRIPTION:$1.|GROUPID:best.|ISACTIVE:best.|NAME:$11.|
+|---|---|---|---|
+|`The group description`|`2 `|`1 `|`mynewergroup `|
+
+
+
+
SAS Macros
+ @li mf_getuniquefileref.sas
+ @li mf_getuniquelibref.sas
+ @li mp_abort.sas
+
+ Related Files
+ @li ms_creategroup.test.sas
+ @li ms_getgroups.sas
+
+**/
+
+%macro ms_creategroup(groupname
+ ,desc=0
+ ,isactive=true
+ ,outds=work.ms_creategroup
+ ,mdebug=0
+ );
+
+%mp_abort(
+ iftrue=(&syscc ne 0)
+ ,mac=ms_creategroup.sas
+ ,msg=%str(syscc=&syscc on macro entry)
+)
+
+%local fref0 fref1 fref2 libref optval rc msg;
+%let fref0=%mf_getuniquefileref();
+%let fref1=%mf_getuniquefileref();
+%let fref2=%mf_getuniquefileref();
+%let libref=%mf_getuniquelibref();
+
+/* avoid sending bom marker to API */
+%let optval=%sysfunc(getoption(bomfile));
+options nobomfile;
+
+data _null_;
+ file &fref0 termstr=crlf;
+ name=quote(cats(symget('groupname')));
+ description=quote(cats(symget('desc')));
+ if cats(description)='"0"' then description=name;
+ isactive=symget('isactive');
+%if &mdebug=1 %then %do;
+ putlog _all_;
+%end;
+
+ put '{'@;
+ put '"name":' name @;
+ put ',"description":' description @;
+ put ',"isActive":' isactive @;
+ put '}';
+run;
+
+data _null_;
+ file &fref1 lrecl=1000;
+ infile "&_sasjs_tokenfile" lrecl=1000;
+ input;
+ if _n_=1 then do;
+ put "Content-Type: application/json";
+ put "accept: application/json";
+ end;
+ put _infile_;
+run;
+
+%if &mdebug=1 %then %do;
+ data _null_;
+ infile &fref0;
+ input;
+ put _infile_;
+ data _null_;
+ infile &fref1;
+ input;
+ put _infile_;
+ run;
+%end;
+
+proc http method='POST' in=&fref0 headerin=&fref1 out=&fref2
+ url="&_sasjs_apiserverurl/SASjsApi/group";
+%if &mdebug=1 %then %do;
+ debug level=1;
+%end;
+run;
+
+%mp_abort(
+ iftrue=(&syscc ne 0)
+ ,mac=ms_creategroup.sas
+ ,msg=%str(Issue submitting query to SASjsApi/group)
+)
+
+libname &libref JSON fileref=&fref2;
+
+data &outds;
+ set &libref..root;
+ drop ordinal_root;
+run;
+
+
+%mp_abort(
+ iftrue=(&syscc ne 0)
+ ,mac=ms_creategroup.sas
+ ,msg=%str(Issue reading response JSON)
+)
+
+/* reset options */
+options &optval;
+
+%if &mdebug=1 %then %do;
+ filename &fref0 clear;
+ filename &fref1 clear;
+ filename &fref2 clear;
+ libname &libref clear;
+%end;
+
+%mend ms_creategroup;
diff --git a/server/ms_getgroups.sas b/server/ms_getgroups.sas
new file mode 100644
index 0000000..beba852
--- /dev/null
+++ b/server/ms_getgroups.sas
@@ -0,0 +1,105 @@
+/**
+ @file
+ @brief Fetches the list of groups from SASjs Server
+ @details Fetches the list of groups from SASjs Server and writes them to an
+ output dataset.
+
+ Example:
+
+ %ms_getgroups(outds=userlist)
+
+ @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
+ @param [out] outds= (work.ms_getgroups) This output dataset will contain the
+ list of groups. Format:
+|NAME:$32.|DESCRIPTION:$64.|GROUPID:best.|
+|---|---|---|
+|`SomeGroup `|`A group `|`1`|
+|`Another Group`|`this is a different group`|`2`|
+|`admin`|`Administrators `|`3`|
+
+
+ SAS Macros
+ @li mf_getuniquefileref.sas
+ @li mf_getuniquelibref.sas
+ @li mp_abort.sas
+
+ Related Files
+ @li ms_creategroup.sas
+ @li ms_getusers.test.sas
+
+**/
+
+%macro ms_getgroups(
+ outds=work.ms_getgroups
+ ,mdebug=0
+ );
+
+%mp_abort(
+ iftrue=(&syscc ne 0)
+ ,mac=ms_getusers.sas
+ ,msg=%str(syscc=&syscc on macro entry)
+)
+
+%local fref0 fref1 libref optval rc msg;
+%let fref0=%mf_getuniquefileref();
+%let fref1=%mf_getuniquefileref();
+%let libref=%mf_getuniquelibref();
+
+/* avoid sending bom marker to API */
+%let optval=%sysfunc(getoption(bomfile));
+options nobomfile;
+
+data _null_;
+ file &fref0 lrecl=1000;
+ infile "&_sasjs_tokenfile" lrecl=1000;
+ input;
+ if _n_=1 then put "accept: application/json";
+ put _infile_;
+run;
+
+%if &mdebug=1 %then %do;
+ data _null_;
+ infile &fref0;
+ input;
+ put _infile_;
+ run;
+%end;
+
+proc http method='GET' headerin=&fref0 out=&fref1
+ url="&_sasjs_apiserverurl/SASjsApi/group";
+%if &mdebug=1 %then %do;
+ debug level=1;
+%end;
+run;
+
+%mp_abort(
+ iftrue=(&syscc ne 0)
+ ,mac=ms_getgroups.sas
+ ,msg=%str(Issue submitting GET query to SASjsApi/group)
+)
+
+libname &libref JSON fileref=&fref1;
+
+data &outds;
+ length NAME $32 DESCRIPTION $64. GROUPID 8;
+ if _n_=1 then call missing(of _all_);
+ set &libref..root;
+ drop ordinal_root;
+run;
+
+%mp_abort(
+ iftrue=(&syscc ne 0)
+ ,mac=ms_getusers.sas
+ ,msg=%str(Issue reading response JSON)
+)
+
+/* reset options */
+options &optval;
+
+%if &mdebug=1 %then %do;
+ filename &fref0 clear;
+ filename &fref1 clear;
+ libname &libref clear;
+%end;
+
+%mend ms_getgroups;
diff --git a/tests/serveronly/ms_creategroup.test.sas b/tests/serveronly/ms_creategroup.test.sas
new file mode 100644
index 0000000..0d9597c
--- /dev/null
+++ b/tests/serveronly/ms_creategroup.test.sas
@@ -0,0 +1,50 @@
+/**
+ @file
+ @brief Testing ms_creategroup.sas macro
+
+ SAS Macros
+ @li mf_getuniquename.sas
+ @li mp_assert.sas
+ @li mp_assertscope.sas
+ @li ms_creategroup.sas
+ @li ms_getgroups.sas
+
+**/
+
+%let group=%substr(%mf_getuniquename(),1,8);
+
+%mp_assertscope(SNAPSHOT)
+%ms_creategroup(&group, desc=The description,mdebug=&sasjs_mdebug,outds=test1)
+%mp_assertscope(COMPARE
+ ,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
+)
+
+%let id=0;
+data _null_;
+ set work.test1;
+ call symputx('id',id);
+run;
+%mp_assert(
+ iftrue=(&id>0),
+ desc=Checking that group was created with an ID,
+ outds=work.test_results
+)
+
+/* double check by querying the list of users */
+%ms_getgroups(outds=work.test2)
+%let checkid=0;
+data _null_;
+ set work.test2;
+ where name="&group";
+ call symputx('checkid',id);
+run;
+%mp_assert(
+ iftrue=(&checkid=&id),
+ desc=Checking that fetched group exists and has the same ID,
+ outds=work.test_results
+)
+
+
+
+
+
diff --git a/tests/serveronly/ms_getgroups.test.sas b/tests/serveronly/ms_getgroups.test.sas
new file mode 100644
index 0000000..b0eebcf
--- /dev/null
+++ b/tests/serveronly/ms_getgroups.test.sas
@@ -0,0 +1,23 @@
+/**
+ @file
+ @brief Testing ms_getgroups.sas macro
+
+ SAS Macros
+ @li ms_getgroups.sas
+ @li mp_assertdsobs.sas
+ @li mp_assertscope.sas
+
+**/
+
+
+%mp_assertscope(SNAPSHOT)
+%ms_getgroups(outds=work.test1,mdebug=&sasjs_mdebug)
+%mp_assertscope(COMPARE
+ ,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
+)
+
+%mp_assertdsobs(work.test1,test=ATLEAST 1)
+
+
+
+