diff --git a/api/.env.defaults b/api/.env.defaults
index 63d5e94dc49793acee86be230ae90ff3783eff32..e94e8c27922e77468d92961b311feac1c081608b 100644
--- a/api/.env.defaults
+++ b/api/.env.defaults
@@ -1,3 +1,3 @@
-ENGINE_TYPE=exareme
-ENGINE_BASE_URL=http://127.0.0.1:8080/services/
+ENGINE_TYPE=csv
+ENGINE_BASE_URL=https://docs.google.com/spreadsheets/d/1yjslZQCOMCxkjr4xQ-NmTMNEjhpdmZgijbn83za80Ak/export?format=tsv
 GATEWAY_PORT=8081
\ No newline at end of file
diff --git a/api/src/engine/connectors/csv/main.connector.ts b/api/src/engine/connectors/csv/main.connector.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eedb7ae6b31074fbe1e5c66970aa008f62859004
--- /dev/null
+++ b/api/src/engine/connectors/csv/main.connector.ts
@@ -0,0 +1,173 @@
+import { firstValueFrom, Observable } from 'rxjs';
+import { IEngineOptions, IEngineService } from 'src/engine/engine.interfaces';
+import { Domain } from 'src/engine/models/domain.model';
+import { ExperimentCreateInput } from 'src/engine/models/experiment/input/experiment-create.input';
+import {
+  Experiment,
+  PartialExperiment,
+} from 'src/engine/models/experiment/experiment.model';
+import { ListExperiments } from 'src/engine/models/experiment/list-experiments.model';
+import { ExperimentEditInput } from 'src/engine/models/experiment/input/experiment-edit.input';
+import { Algorithm } from 'src/engine/models/experiment/algorithm.model';
+import { HttpService } from '@nestjs/axios';
+import { Group } from 'src/engine/models/group.model';
+import { Dictionary } from 'src/common/interfaces/utilities.interface';
+
+export default class CSVService implements IEngineService {
+  constructor(
+    private readonly options: IEngineOptions,
+    private readonly httpService: HttpService,
+  ) {}
+
+  getAlgorithms(): Algorithm[] | Promise<Algorithm[]> {
+    throw new Error('Method not implemented.');
+  }
+
+  createExperiment(
+    data: ExperimentCreateInput,
+    isTransient: boolean,
+  ): Experiment | Promise<Experiment> {
+    throw new Error('Method not implemented.');
+  }
+
+  listExperiments(
+    page: number,
+    name: string,
+  ): ListExperiments | Promise<ListExperiments> {
+    throw new Error('Method not implemented.');
+  }
+
+  getExperiment(uuid: string): Experiment | Promise<Experiment> {
+    throw new Error('Method not implemented.');
+  }
+
+  removeExperiment(
+    uuid: string,
+  ): PartialExperiment | Promise<PartialExperiment> {
+    throw new Error('Method not implemented.');
+  }
+
+  editExperient(
+    uuid: string,
+    expriment: ExperimentEditInput,
+  ): Experiment | Promise<Experiment> {
+    throw new Error('Method not implemented.');
+  }
+
+  async getDomains(): Promise<Domain[]> {
+    const path = this.options.baseurl;
+
+    const { data } = await firstValueFrom(this.httpService.get<string>(path));
+
+    const rows = data
+      .split('\r\n')
+      .map((row) => row.split('\t').filter((i) => i))
+      .filter((row) => row.length >= 2);
+
+    rows.shift(); // remove headers
+
+    const vars = [];
+    const groups: Dictionary<Group> = {};
+    const rootGroup: Group = {
+      id: 'Global group',
+      groups: [],
+    };
+
+    rows.forEach((row) => {
+      const variable = {
+        id: row[0].toLowerCase(),
+        label: row[0],
+      };
+
+      row.shift(); // get ride of the variable name, keep only groups
+
+      vars.push(variable);
+
+      row
+        .filter((group) => !groups[group.toLowerCase()])
+        .forEach((group, i) => {
+          const groupId = group.toLowerCase();
+          if (i === 0) rootGroup.groups.push(groupId);
+          groups[groupId] = {
+            id: groupId,
+            label: group,
+            variables: [],
+            groups: [],
+          };
+        });
+
+      const groupId = row[row.length - 1].toLowerCase(); // group's variable container
+
+      groups[groupId].variables.push(variable.id); // add variable
+
+      row
+        .reverse()
+        .map((group) => group.toLowerCase())
+        .forEach((group, i) => {
+          const groupId = group.toLowerCase();
+
+          if (i !== row.length - 1) {
+            const parentId = row[i + 1].toLowerCase();
+            if (groups[parentId].groups.indexOf(groupId) === -1)
+              groups[parentId].groups.push(groupId);
+          }
+        });
+    });
+
+    rootGroup.groups = [...new Set(rootGroup.groups)]; // get distinct values
+
+    return [
+      {
+        id: 'Dummy',
+        label: 'Dummy',
+        datasets: [{ id: 'DummyDataset', label: 'Dummy Dataset' }],
+        groups: Object.values(groups),
+        rootGroup: rootGroup,
+        variables: vars,
+      },
+    ];
+  }
+
+  getActiveUser(): string {
+    const dummyUser = {
+      username: 'anonymous',
+      subjectId: 'anonymousId',
+      fullname: 'anonymous',
+      email: 'anonymous@anonymous.com',
+      agreeNDA: true,
+    };
+    return JSON.stringify(dummyUser);
+  }
+
+  editActiveUser(): Observable<string> {
+    throw new Error('Method not implemented.');
+  }
+
+  getExperimentREST(): Observable<string> {
+    throw new Error('Method not implemented.');
+  }
+
+  deleteExperiment(): Observable<string> {
+    throw new Error('Method not implemented.');
+  }
+
+  editExperimentREST(): Observable<string> {
+    throw new Error('Method not implemented.');
+  }
+
+  startExperimentTransient(): Observable<string> {
+    throw new Error('Method not implemented.');
+  }
+
+  startExperiment(): Observable<string> {
+    throw new Error('Method not implemented.');
+  }
+
+  getExperiments(): string {
+    return '[]';
+  }
+
+  getAlgorithmsREST(): string {
+    return '[]';
+  }
+}
diff --git a/api/src/engine/connectors/exareme/converters.ts b/api/src/engine/connectors/exareme/converters.ts
index 07fb2b4b0cfa378b1950147be5862307d4ff4ea9..ab840843a6c698c24142eb228343d819584ee8a6 100644
--- a/api/src/engine/connectors/exareme/converters.ts
+++ b/api/src/engine/connectors/exareme/converters.ts
@@ -27,7 +27,9 @@ export const dataToGroup = (data: Hierarchy): Group => {
   return {
     id: data.code,
     label: data.label,
-    groups: data.groups ? data.groups.map(dataToGroup) : [],
+    groups: data.groups
+      ? data.groups.map(dataToGroup).map((group) => group.id)
+      : [],
     variables: data.variables
       ? data.variables.map((data: VariableEntity) => data.code)
       : [],
diff --git a/api/src/engine/models/group.model.ts b/api/src/engine/models/group.model.ts
index 6c4880262e3a538114f3e4717d9c4ddabf7a061d..6a23f1983398f81eeca84731c3d8cfe4b92b599a 100644
--- a/api/src/engine/models/group.model.ts
+++ b/api/src/engine/models/group.model.ts
@@ -6,8 +6,8 @@ export class Group extends Entity {
   @Field({ nullable: true })
   description?: string;
 
-  @Field(() => [Group], { defaultValue: [], nullable: true })
-  groups?: Group[];
+  @Field(() => [String], { defaultValue: [], nullable: true })
+  groups?: string[];
 
   @Field(() => [String], {
     description: "List of variable's ids",
diff --git a/api/src/engine/models/variable.model.ts b/api/src/engine/models/variable.model.ts
index 8650f48b1044bb07c88964ae36aeb00d0d9a3d1b..bd54afed70a025ce6c5673bf0627a657d77926cb 100644
--- a/api/src/engine/models/variable.model.ts
+++ b/api/src/engine/models/variable.model.ts
@@ -5,8 +5,8 @@ import { Group } from './group.model';
 
 @ObjectType()
 export class Variable extends Entity {
-  @Field()
-  type: string;
+  @Field({ nullable: true })
+  type?: string;
 
   @Field({ nullable: true })
   description?: string;
diff --git a/api/src/schema.gql b/api/src/schema.gql
index c906a1951ce36cba5961ced0c2853ef6ddb2658c..86b31a4d2dcb38a15ab00200462ce2c5bd220d97 100644
--- a/api/src/schema.gql
+++ b/api/src/schema.gql
@@ -11,7 +11,7 @@ type Group {
   id: String!
   label: String
   description: String
-  groups: [Group!]
+  groups: [String!]
 
   """List of variable's ids"""
   variables: [String!]
@@ -20,7 +20,7 @@ type Group {
 type Variable {
   id: String!
   label: String
-  type: String!
+  type: String
   description: String
   enumerations: [Category!]
   groups: [Group!]