diff --git a/api/package-lock.json b/api/package-lock.json
index 6f50c98fcb8f360b97b14a52408e77063f952e33..88182859b9a42510792332bff648111830b823b3 100644
--- a/api/package-lock.json
+++ b/api/package-lock.json
@@ -19,6 +19,7 @@
         "apollo-server-express": "^3.3.0",
         "axios": "^0.21.1",
         "graphql": "^15.5.3",
+        "graphql-type-json": "^0.3.2",
         "jsonata": "^1.8.5",
         "reflect-metadata": "^0.1.13",
         "rimraf": "^3.0.2",
@@ -5582,6 +5583,14 @@
         "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0"
       }
     },
+    "node_modules/graphql-type-json": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.2.tgz",
+      "integrity": "sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==",
+      "peerDependencies": {
+        "graphql": ">=0.8.0"
+      }
+    },
     "node_modules/graphql-ws": {
       "version": "5.4.0",
       "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.4.0.tgz",
@@ -14888,6 +14897,12 @@
         "tslib": "^2.1.0"
       }
     },
+    "graphql-type-json": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.2.tgz",
+      "integrity": "sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==",
+      "requires": {}
+    },
     "graphql-ws": {
       "version": "5.4.0",
       "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.4.0.tgz",
diff --git a/api/package.json b/api/package.json
index fd94af7dcea0a56fcf453b755939a3a373c8b459..1885442d70f4ac545ac7fc662ec9bef27d1d21de 100644
--- a/api/package.json
+++ b/api/package.json
@@ -32,6 +32,7 @@
     "apollo-server-express": "^3.3.0",
     "axios": "^0.21.1",
     "graphql": "^15.5.3",
+    "graphql-type-json": "^0.3.2",
     "jsonata": "^1.8.5",
     "reflect-metadata": "^0.1.13",
     "rimraf": "^3.0.2",
diff --git a/api/src/engine/connectors/datashield/main.connector.ts b/api/src/engine/connectors/datashield/main.connector.ts
index 1cdbb509c93a78794235c371c6fb3a62076b4792..45bf43a1df7f8fc7877f297a69e5edf6eec50d6d 100644
--- a/api/src/engine/connectors/datashield/main.connector.ts
+++ b/api/src/engine/connectors/datashield/main.connector.ts
@@ -1,21 +1,43 @@
 import { Observable } from 'rxjs';
 import { IEngineService } from 'src/engine/engine.interfaces';
 import { Domain } from 'src/engine/models/domain.model';
-import { ExperimentCreateInput } from 'src/engine/models/experiment/experiment-create.input';
-import { Experiment } from 'src/engine/models/experiment/experiment.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';
 
 export default class DataShieldService implements IEngineService {
-  createTransient(
+  createExperiment(
     data: ExperimentCreateInput,
+    isTransient: boolean,
   ): Experiment | Promise<Experiment> {
     throw new Error('Method not implemented.');
   }
-  getDomains(): Domain[] {
+  listExperiments(
+    page: number,
+    name: string,
+  ): ListExperiments | Promise<ListExperiments> {
     throw new Error('Method not implemented.');
   }
-
-  demo(): string {
-    return 'datashield';
+  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.');
+  }
+  getDomains(): Domain[] {
+    throw new Error('Method not implemented.');
   }
 
   getActiveUser(): Observable<string> {
@@ -26,7 +48,7 @@ export default class DataShieldService implements IEngineService {
     throw new Error('Method not implemented.');
   }
 
-  getExperiment(): Observable<string> {
+  getExperimentAPI(): Observable<string> {
     throw new Error('Method not implemented.');
   }
 
@@ -34,7 +56,7 @@ export default class DataShieldService implements IEngineService {
     throw new Error('Method not implemented.');
   }
 
-  editExperiment(): Observable<string> {
+  editExperimentAPI(): Observable<string> {
     throw new Error('Method not implemented.');
   }
 
diff --git a/api/src/engine/connectors/exareme/converters.ts b/api/src/engine/connectors/exareme/converters.ts
index cb1c884c6101bec8de814accda529690cb92896f..05b9711b0a989e4df868fa53c480c881cb18b2ed 100644
--- a/api/src/engine/connectors/exareme/converters.ts
+++ b/api/src/engine/connectors/exareme/converters.ts
@@ -1,14 +1,25 @@
 import { Category } from 'src/engine/models/category.model';
-import { ExperimentCreateInput } from 'src/engine/models/experiment/experiment-create.input';
+import { AlgorithmParameter } from 'src/engine/models/experiment/algorithm-parameter.model';
 import { Experiment } from 'src/engine/models/experiment/experiment.model';
+import { ExperimentCreateInput } from 'src/engine/models/experiment/input/experiment-create.input';
 import { Group } from 'src/engine/models/group.model';
-import { TableResult } from 'src/engine/models/result/table-result.model';
+import { ResultUnion } from 'src/engine/models/result/common/result-union.model';
+import {
+  GroupResult,
+  GroupsResult,
+} from 'src/engine/models/result/groups-result.model';
+import { RawResult } from 'src/engine/models/result/raw-result.model';
 import { Variable } from 'src/engine/models/variable.model';
 import { Entity } from './interfaces/entity.interface';
+import { ExperimentData } from './interfaces/experiment/experiment.interface';
+import { ResultExperiment } from './interfaces/experiment/result-experiment.interface';
 import { Hierarchy } from './interfaces/hierarchy.interface';
-import { TransientDataResult } from './interfaces/transient/transient-data-result.interface';
 import { VariableEntity } from './interfaces/variable-entity.interface';
-import { transientToTable } from './transformations';
+import {
+  descriptiveModelToTables,
+  descriptiveSingleToTables,
+  transformToExperiment,
+} from './transformations';
 
 export const dataToGroup = (data: Hierarchy): Group => {
   return {
@@ -39,6 +50,13 @@ export const dataToVariable = (data: VariableEntity): Variable => {
   };
 };
 
+const algoParamInputToData = (param: AlgorithmParameter) => {
+  return {
+    name: param.name,
+    value: param.value.join(','),
+  };
+};
+
 export const experimentInputToData = (data: ExperimentCreateInput) => {
   return {
     algorithm: {
@@ -47,10 +65,6 @@ export const experimentInputToData = (data: ExperimentCreateInput) => {
           name: 'dataset',
           value: data.datasets.join(','),
         },
-        {
-          name: 'y',
-          value: data.variables.join(','),
-        },
         {
           name: 'filter',
           value: data.filter,
@@ -59,19 +73,85 @@ export const experimentInputToData = (data: ExperimentCreateInput) => {
           name: 'pathology',
           value: data.domain,
         },
-      ],
-      type: 'string',
-      name: data.algorithm,
+        {
+          name: 'y',
+          value: data.variables.join(','),
+        },
+      ].concat(data.algorithm.parameters.map(algoParamInputToData)),
+      type: data.algorithm.type ?? 'string',
+      name: data.algorithm.name,
     },
     name: data.name,
   };
 };
 
-export const dataToTransient = (data: TransientDataResult): Experiment => {
-  const tabs: TableResult[] = transientToTable.evaluate(data);
+export const descriptiveDataToTableResult = (
+  data: ResultExperiment,
+): GroupsResult[] => {
+  const result = new GroupsResult();
 
-  return {
-    title: data.name,
-    results: tabs,
+  result.groups = [
+    new GroupResult({
+      name: 'Single',
+      results: descriptiveSingleToTables.evaluate(data),
+    }),
+  ];
+
+  result.groups.push(
+    new GroupResult({
+      name: 'Model',
+      results: descriptiveModelToTables.evaluate(data),
+    }),
+  );
+
+  return [result];
+};
+
+export const dataToExperiment = (data: ExperimentData): Experiment => {
+  const expTransform = transformToExperiment.evaluate(data);
+
+  const exp: Experiment = {
+    ...expTransform,
+    results: [],
   };
+
+  exp.results = data.result
+    ? data.result
+        .map((result) => dataToResult(result, exp.algorithm.name))
+        .flat()
+    : [];
+
+  return exp;
+};
+
+export const dataToRaw = (result: ResultExperiment): RawResult[] => {
+  return [
+    {
+      data: result.data,
+    },
+  ];
+};
+
+export const dataToResult = (
+  result: ResultExperiment,
+  algo: string,
+): Array<typeof ResultUnion> => {
+  switch (result.type.toLowerCase()) {
+    case 'application/json':
+      return dataJSONtoResult(result, algo);
+    default:
+      return dataToRaw(result);
+  }
+};
+
+export const dataJSONtoResult = (
+  result: ResultExperiment,
+  algo: string,
+): Array<typeof ResultUnion> => {
+  switch (algo.toLowerCase()) {
+    case 'descriptive_stats':
+      return descriptiveDataToTableResult(result);
+    default:
+      return [];
+  }
 };
diff --git a/api/src/engine/connectors/exareme/interfaces/experiment/experiment.interface.ts b/api/src/engine/connectors/exareme/interfaces/experiment/experiment.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7412cb0560c9eda88fe61dd4ebbf8128c94e2c62
--- /dev/null
+++ b/api/src/engine/connectors/exareme/interfaces/experiment/experiment.interface.ts
@@ -0,0 +1,11 @@
+import { ResultExperiment } from './result-experiment.interface';
+
+export interface ExperimentData {
+  name: string;
+  uuid?: string;
+  status?: string;
+  createdBy?: string;
+  shared?: boolean;
+  viewed?: boolean;
+  result?: ResultExperiment[];
+}
diff --git a/api/src/engine/connectors/exareme/interfaces/experiment/experiments.interface.ts b/api/src/engine/connectors/exareme/interfaces/experiment/experiments.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5ef0c0f84568d7a7e87dd1f759c1db3b17e8066a
--- /dev/null
+++ b/api/src/engine/connectors/exareme/interfaces/experiment/experiments.interface.ts
@@ -0,0 +1,8 @@
+import { ExperimentData } from './experiment.interface';
+
+export interface ExperimentsData {
+  experiments: ExperimentData[];
+  currentpage?: number;
+  totalExperiments?: number;
+  totalPages?: number;
+}
diff --git a/api/src/engine/connectors/exareme/interfaces/experiment/result-experiment.interface.ts b/api/src/engine/connectors/exareme/interfaces/experiment/result-experiment.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e655151c9e7b113a2dbff0402d8e99c61534adee
--- /dev/null
+++ b/api/src/engine/connectors/exareme/interfaces/experiment/result-experiment.interface.ts
@@ -0,0 +1,4 @@
+export interface ResultExperiment {
+  data: unknown;
+  type: string;
+}
diff --git a/api/src/engine/connectors/exareme/interfaces/transient/transient-data-result.interface.ts b/api/src/engine/connectors/exareme/interfaces/transient/transient-data-result.interface.ts
deleted file mode 100644
index 37a62f96b071c594696f01bd3b27d75d2bc25f67..0000000000000000000000000000000000000000
--- a/api/src/engine/connectors/exareme/interfaces/transient/transient-data-result.interface.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-export interface NumericalData {
-  [key: string]: number;
-}
-
-export interface CategoricalData {
-  [key: string]: {
-    count: number;
-    percentage: number;
-  };
-}
-
-export interface TransientDataResult {
-  name: string;
-  result: [
-    {
-      data: {
-        single: {
-          [variable: string]: {
-            [dataset: string]: {
-              data: NumericalData | CategoricalData;
-              num_datapoints: number;
-              num_total: number;
-              num_nulls: number;
-            };
-          };
-        };
-        model: {
-          [dataset: string]: {
-            data: {
-              [variable: string]: {
-                [key: string]: number;
-              };
-            };
-            num_datapoints: number;
-            num_total: number;
-            num_nulls: number;
-          };
-        };
-      };
-    },
-  ];
-}
diff --git a/api/src/engine/connectors/exareme/main.connector.ts b/api/src/engine/connectors/exareme/main.connector.ts
index 75f21b56698ea59dbc65a88b4edf1ea014163e48..81ed14ab64999708295fd7bbbc38678994d1ba86 100644
--- a/api/src/engine/connectors/exareme/main.connector.ts
+++ b/api/src/engine/connectors/exareme/main.connector.ts
@@ -1,23 +1,29 @@
 import { HttpService } from '@nestjs/axios';
-import { HttpException, HttpStatus } from '@nestjs/common';
+import { BadRequestException, HttpException, HttpStatus } from '@nestjs/common';
 import { Request } from 'express';
 import { firstValueFrom, map, 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/experiment-create.input';
-import { Experiment } from 'src/engine/models/experiment/experiment.model';
+import {
+  Experiment,
+  PartialExperiment,
+} from 'src/engine/models/experiment/experiment.model';
+import { ExperimentCreateInput } from 'src/engine/models/experiment/input/experiment-create.input';
+import { ExperimentEditInput } from 'src/engine/models/experiment/input/experiment-edit.input';
+import { ListExperiments } from 'src/engine/models/experiment/list-experiments.model';
 import { Group } from 'src/engine/models/group.model';
 import { Variable } from 'src/engine/models/variable.model';
 import {
   dataToCategory,
+  dataToExperiment,
   dataToGroup,
-  dataToTransient,
   dataToVariable,
   experimentInputToData,
 } from './converters';
+import { ExperimentData } from './interfaces/experiment/experiment.interface';
+import { ExperimentsData } from './interfaces/experiment/experiments.interface';
 import { Hierarchy } from './interfaces/hierarchy.interface';
 import { Pathology } from './interfaces/pathology.interface';
-import { TransientDataResult } from './interfaces/transient/transient-data-result.interface';
 
 export default class ExaremeService implements IEngineService {
   constructor(
@@ -25,16 +31,69 @@ export default class ExaremeService implements IEngineService {
     private readonly httpService: HttpService,
   ) {}
 
-  async createTransient(data: ExperimentCreateInput): Promise<Experiment> {
+  async createExperiment(
+    data: ExperimentCreateInput,
+    isTransient = false,
+  ): Promise<Experiment> {
     const form = experimentInputToData(data);
 
-    const path = this.options.baseurl + 'experiments/transient';
+    const path =
+      this.options.baseurl + `experiments${isTransient ? '/transient' : ''}`;
+
+    const resultAPI = await firstValueFrom(
+      this.httpService.post<ExperimentData>(path, form),
+    );
+
+    return dataToExperiment(resultAPI.data);
+  }
+
+  async listExperiments(page: number, name: string): Promise<ListExperiments> {
+    const path = this.options.baseurl + 'experiments';
+
+    const resultAPI = await firstValueFrom(
+      this.httpService.get<ExperimentsData>(path, { params: { page, name } }),
+    );
+
+    return {
+      ...resultAPI.data,
+      experiments: resultAPI.data.experiments.map(dataToExperiment),
+    };
+  }
+
+  async getExperiment(uuid: string): Promise<Experiment> {
+    const path = this.options.baseurl + `experiments/${uuid}`;
 
     const resultAPI = await firstValueFrom(
-      this.httpService.post<TransientDataResult>(path, form),
+      this.httpService.get<ExperimentData>(path),
     );
 
-    return dataToTransient(resultAPI.data);
+    return dataToExperiment(resultAPI.data);
+  }
+
+  async editExperient(
+    uuid: string,
+    expriment: ExperimentEditInput,
+  ): Promise<Experiment> {
+    const path = this.options.baseurl + `experiments/${uuid}`;
+
+    const resultAPI = await firstValueFrom(
+      this.httpService.patch<ExperimentData>(path, expriment),
+    );
+
+    return dataToExperiment(resultAPI.data);
+  }
+
+  async removeExperiment(uuid: string): Promise<PartialExperiment> {
+    const path = this.options.baseurl + `experiments/${uuid}`;
+
+    try {
+      await firstValueFrom(this.httpService.delete(path));
+      return {
+        uuid: uuid,
+      };
+    } catch (error) {
+      throw new BadRequestException(`${uuid} does not exists`);
+    }
   }
 
   async getDomains(ids: string[]): Promise<Domain[]> {
@@ -85,7 +144,7 @@ export default class ExaremeService implements IEngineService {
       .pipe(map((response) => response.data));
   }
 
-  getExperiment(uuid: string): Observable<string> {
+  getExperimentAPI(uuid: string): Observable<string> {
     const path = this.options.baseurl + `experiments/${uuid}`;
 
     return this.httpService
@@ -99,11 +158,11 @@ export default class ExaremeService implements IEngineService {
     return this.httpService.delete(path).pipe(map((response) => response.data));
   }
 
-  editExperiment(uuid: string, request: Request): Observable<string> {
+  editExperimentAPI(uuid: string, request: Request): Observable<string> {
     const path = this.options.baseurl + `experiments/${uuid}`;
 
     return this.httpService
-      .post(path, request.body)
+      .patch(path, request.body)
       .pipe(map((response) => response.data));
   }
 
@@ -123,22 +182,23 @@ export default class ExaremeService implements IEngineService {
       .pipe(map((response) => response.data));
   }
 
-  getExperiments(): Observable<string> {
+  getExperiments(request: Request): Observable<string> {
     const path = this.options.baseurl + 'experiments';
 
     return this.httpService
-      .get<string>(path)
+      .get<string>(path, { params: request.query })
       .pipe(map((response) => response.data));
   }
 
-  getAlgorithms(): Observable<string> {
+  getAlgorithms(request: Request): Observable<string> {
     const path = this.options.baseurl + 'algorithms';
 
     return this.httpService
-      .get<string>(path)
+      .get<string>(path, { params: request.query })
       .pipe(map((response) => response.data));
   }
 
+  // UTILITIES
   private flattenGroups = (data: Hierarchy): Group[] => {
     let groups: Group[] = [dataToGroup(data)];
 
diff --git a/api/src/engine/connectors/exareme/transformations.ts b/api/src/engine/connectors/exareme/transformations.ts
index 5a03098b673d393dcffa8eb33aada2c71bef65d1..8df362c42f17978d07357fdee8e6d793c48dab09 100644
--- a/api/src/engine/connectors/exareme/transformations.ts
+++ b/api/src/engine/connectors/exareme/transformations.ts
@@ -3,27 +3,93 @@
 
 import * as jsonata from 'jsonata'; // old import style needed due to 'export = jsonata'
 
-export const transientToTable = jsonata(`
+export const transformToExperiment = jsonata(`
 ( 
-    $trim := function($v) {$v.$string().$replace(/(\\d+\\.\\d{1,3})(\\d*)/, "$1")};
+    $params := ["y", "pathology", "dataset", "filter"];
 
-    $e := function($x, $r) {($x != null) ? $trim($x) : ($r ? $r : '')};
+    {
+        "name": name,
+        "uuid": uuid,
+        "author": createdBy,
+        "viewed": viewed,
+        "status": status,
+        "createdAt": created,
+        "finishedAt": finished,
+        "shared": shared,
+        "updateAt": updated,
+        "domains": algorithm.parameters[name = "pathology"].value,
+        "variables": $split(algorithm.parameters[name = "y"].value, ','),
+        "filter": algorithm.parameters[name = "filter"].value,
+        "datasets": $split(algorithm.parameters[name = "dataset"].value, ','),
+        "algorithm": {
+            "name": algorithm.name,
+            "parameters" : 
+                algorithm.parameters[$not(name in $params)].({
+                    "name": name,
+                    "label": label,
+                    "value": value
+                })
+        }
+    }
+)
+`);
+
+const headerDescriptivie = `
+$e := function($x, $r) {($x != null) ? $fnum($x) : ($r ? $r : '')};
+    
+$fnum := function($x) { $type($x) = 'number' ? $round($number($x),3) : $x };
+
+$fn := function($o, $prefix) {
+    $type($o) = 'object' ? 
+    $each($o, function($v, $k) {(
+        $type($v) = 'object' ? { $k: $v.count & ' (' & $v.percentage & '%)' } : {
+            $k: $v
+        }
+    )}) ~> $merge()
+    : {}
+};`;
+
+export const descriptiveModelToTables = jsonata(`
+(   
+    ${headerDescriptivie}
+
+    $vars := $count(data.single.*)-1;
+    $varName := $keys(data.single);
+    $model := data.model;
+
+    [[0..$vars].(
+        $i := $;
+        $ks := $keys($model.*.data.*[$i][$type($) = 'object']);
+        {
+            'name': $varName[$i],
+            'headers': $append("", $keys($$.data.model)).{
+                'name': $,
+                'type': 'string'
+            },
+            'data': [
+                [$varName[$i], $model.*.($e(num_total))],
+                ['Datapoints', $model.*.($e(num_datapoints))],
+                ['Nulls', $model.*.($e(num_nulls))],
+                 $model.*.data.($fn($.*[$i])) ~> $reduce(function($a, $b) {
+                    $map($ks, function($k) {(
+                        {
+                            $k : [$e($lookup($a,$k), "No data"), $e($lookup($b,$k), "No data")]
+                        }
+                    )}) ~> $merge()
+                }) ~> $each(function($v, $k) {$append($k,$v)})
+            ]
+        }
+    )]  
+)`);
 
-    $fn := function($o, $prefix) {
-        $type($o) = 'object' ? 
-        $each($o, function($v, $k) {(
-            $type($v) = 'object' ? { $k: $v.count & ' (' & $v.percentage & '%)' } : {
-                $k: $v
-            }
-        )}) ~> $merge()
-        : {}
-    };
+export const descriptiveSingleToTables = jsonata(`
+( 
+    ${headerDescriptivie}
 
-    result.data.[
+    data.[
         $.single.*@$p#$i.(
             $ks := $keys($p.*.data[$type($) = 'object']);
             {
-            'groupBy' : 'single',
             'name': $keys(%)[$i],
             'headers': $append("", $keys(*)).{
                 'name': $,
diff --git a/api/src/engine/engine.controller.ts b/api/src/engine/engine.controller.ts
index c54f0ce0fa44732ed4fc614caf5ff0509d6e0068..b3e12d13ff2b2004e576f05b4358991f27eabd08 100644
--- a/api/src/engine/engine.controller.ts
+++ b/api/src/engine/engine.controller.ts
@@ -31,7 +31,7 @@ export class EngineController {
 
   @Get('/experiments/:uuid')
   getExperiment(@Param('uuid') uuid: string): Observable<string> {
-    return this.engineService.getExperiment(uuid);
+    return this.engineService.getExperimentAPI(uuid);
   }
 
   @Delete('/experiments/:uuid')
@@ -47,7 +47,7 @@ export class EngineController {
     @Param('uuid') uuid: string,
     @Req() request: Request,
   ): Observable<string> {
-    return this.engineService.editExperiment(uuid, request);
+    return this.engineService.editExperimentAPI(uuid, request);
   }
 
   @Post('experiments/transient')
diff --git a/api/src/engine/engine.interfaces.ts b/api/src/engine/engine.interfaces.ts
index 0d90e92e62de3e342cc206f4579a2bf399df1f36..e754a1fd068a47d1f235fb4ca54a692fd4470342 100644
--- a/api/src/engine/engine.interfaces.ts
+++ b/api/src/engine/engine.interfaces.ts
@@ -1,8 +1,13 @@
 import { Request } from 'express';
 import { Observable } from 'rxjs';
 import { Domain } from './models/domain.model';
-import { ExperimentCreateInput } from './models/experiment/experiment-create.input';
-import { Experiment } from './models/experiment/experiment.model';
+import {
+  Experiment,
+  PartialExperiment,
+} from './models/experiment/experiment.model';
+import { ExperimentCreateInput } from './models/experiment/input/experiment-create.input';
+import { ExperimentEditInput } from './models/experiment/input/experiment-edit.input';
+import { ListExperiments } from './models/experiment/list-experiments.model';
 
 export interface IEngineOptions {
   type: string;
@@ -10,24 +15,43 @@ export interface IEngineOptions {
 }
 
 export interface IEngineService {
+  //GraphQL
   getDomains(ids: string[]): Domain[] | Promise<Domain[]>;
 
+  createExperiment(
+    data: ExperimentCreateInput,
+    isTransient: boolean,
+  ): Promise<Experiment> | Experiment;
+
+  listExperiments(
+    page: number,
+    name: string,
+  ): Promise<ListExperiments> | ListExperiments;
+
+  getExperiment(uuid: string): Promise<Experiment> | Experiment;
+
+  removeExperiment(
+    uuid: string,
+  ): Promise<PartialExperiment> | PartialExperiment;
+
+  editExperient(
+    uuid: string,
+    expriment: ExperimentEditInput,
+  ): Promise<Experiment> | Experiment;
+
+  // Standard REST API call
   getAlgorithms(request: Request): Observable<string>;
 
   getExperiments(request: Request): Observable<string>;
 
-  getExperiment(uuid: string): Observable<string>;
+  getExperimentAPI(uuid: string): Observable<string>;
 
   deleteExperiment(uuid: string, request: Request): Observable<string>;
 
-  editExperiment(uuid: string, request: Request): Observable<string>;
+  editExperimentAPI(uuid: string, request: Request): Observable<string>;
 
   startExperimentTransient(request: Request): Observable<string>;
 
-  createTransient(
-    data: ExperimentCreateInput,
-  ): Promise<Experiment> | Experiment;
-
   startExperiment(request: Request): Observable<string>;
 
   getActiveUser(request: Request): Observable<string>;
diff --git a/api/src/engine/engine.resolver.ts b/api/src/engine/engine.resolver.ts
index e3de433e113e0e13577372240cda4114aa02a193..a954ed3b004e46c8b2cce19ebbc327ac24c2abfe 100644
--- a/api/src/engine/engine.resolver.ts
+++ b/api/src/engine/engine.resolver.ts
@@ -3,8 +3,13 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
 import { ENGINE_SERVICE } from './engine.constants';
 import { IEngineService } from './engine.interfaces';
 import { Domain } from './models/domain.model';
-import { ExperimentCreateInput } from './models/experiment/experiment-create.input';
-import { Experiment } from './models/experiment/experiment.model';
+import {
+  Experiment,
+  PartialExperiment,
+} from './models/experiment/experiment.model';
+import { ExperimentCreateInput } from './models/experiment/input/experiment-create.input';
+import { ExperimentEditInput } from './models/experiment/input/experiment-edit.input';
+import { ListExperiments } from './models/experiment/list-experiments.model';
 
 @Resolver()
 export class EngineResolver {
@@ -20,10 +25,43 @@ export class EngineResolver {
     return this.engineService.getDomains(ids);
   }
 
+  @Query(() => ListExperiments)
+  async experiments(
+    @Args('page', { nullable: true, defaultValue: 0 }) page: number,
+    @Args('name', { nullable: true, defaultValue: '' }) name: string,
+  ) {
+    return this.engineService.listExperiments(page, name);
+  }
+
+  @Query(() => Experiment)
+  async expriment(@Args('uuid') uuid: string) {
+    return this.engineService.getExperiment(uuid);
+  }
+
   @Mutation(() => Experiment)
-  async createTransient(
+  async createExperiment(
     @Args('data') experimentCreateInput: ExperimentCreateInput,
+    @Args('isTransient', { nullable: true, defaultValue: false })
+    isTransient: boolean,
   ) {
-    return this.engineService.createTransient(experimentCreateInput);
+    return this.engineService.createExperiment(
+      experimentCreateInput,
+      isTransient,
+    );
+  }
+
+  @Mutation(() => Experiment)
+  async editExperiment(
+    @Args('uuid') uuid: string,
+    @Args('data') experiment: ExperimentEditInput,
+  ) {
+    return this.engineService.editExperient(uuid, experiment);
+  }
+
+  @Mutation(() => PartialExperiment)
+  async removeExperiment(
+    @Args('uuid') uuid: string,
+  ): Promise<PartialExperiment> {
+    return this.engineService.removeExperiment(uuid);
   }
 }
diff --git a/api/src/engine/models/experiment/algorithm-parameter.model.ts b/api/src/engine/models/experiment/algorithm-parameter.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..79666de79a81e2a7d3c2e2c0756404a995479735
--- /dev/null
+++ b/api/src/engine/models/experiment/algorithm-parameter.model.ts
@@ -0,0 +1,10 @@
+import { Field, ObjectType } from '@nestjs/graphql';
+
+@ObjectType()
+export class AlgorithmParameter {
+  @Field()
+  name: string;
+
+  @Field(() => [String])
+  value: string[];
+}
diff --git a/api/src/engine/models/experiment/algorithm.model.ts b/api/src/engine/models/experiment/algorithm.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..30087c5b55d07d213508d125ba9eb491920073c2
--- /dev/null
+++ b/api/src/engine/models/experiment/algorithm.model.ts
@@ -0,0 +1,14 @@
+import { Field, ObjectType } from '@nestjs/graphql';
+import { AlgorithmParameter } from './algorithm-parameter.model';
+
+@ObjectType()
+export class Algorithm {
+  @Field()
+  name: string;
+
+  @Field(() => [AlgorithmParameter], { nullable: true, defaultValue: [] })
+  parameters: AlgorithmParameter[];
+
+  @Field()
+  type: string;
+}
diff --git a/api/src/engine/models/experiment/experiment.model.ts b/api/src/engine/models/experiment/experiment.model.ts
index 4e7abaeb1ef440bd449b548069e2187a14057000..06e28b4b2e1c93e8dac7c6e7dc828c706f370c8a 100644
--- a/api/src/engine/models/experiment/experiment.model.ts
+++ b/api/src/engine/models/experiment/experiment.model.ts
@@ -1,44 +1,54 @@
-import {
-  createUnionType,
-  Field,
-  GraphQLISODateTime,
-  ObjectType,
-} from '@nestjs/graphql';
-import { DummyResult } from '../result/dummy-result.model';
-import { TableResult } from '../result/table-result.model';
-
-export const ResultUnion = createUnionType({
-  name: 'ResultUnion',
-  types: () => [TableResult, DummyResult],
-  resolveType(value) {
-    if (value.headers) {
-      return TableResult;
-    }
-    if (value.listMax) {
-      return DummyResult;
-    }
-
-    return null;
-  },
-});
+import { Field, ObjectType, PartialType } from '@nestjs/graphql';
+import { ResultUnion } from '../result/common/result-union.model';
+import { Algorithm } from './algorithm.model';
 
 @ObjectType()
 export class Experiment {
-  @Field()
-  title: string;
-
   @Field({ nullable: true })
   uuid?: string;
 
-  @Field(() => GraphQLISODateTime, { nullable: true })
-  created_at?: Date;
+  @Field({ nullable: true, defaultValue: '' })
+  author?: string;
+
+  @Field({ nullable: true })
+  createdAt?: number;
+
+  @Field({ nullable: true })
+  updateAt?: number;
+
+  @Field({ nullable: true })
+  finishedAt?: number;
+
+  @Field({ nullable: true, defaultValue: false })
+  viewed?: boolean;
+
+  @Field({ nullable: true })
+  status?: string;
 
-  @Field(() => GraphQLISODateTime, { nullable: true })
-  update_at?: Date;
+  @Field({ defaultValue: false })
+  shared?: boolean;
 
-  @Field(() => GraphQLISODateTime, { nullable: true })
-  finished_at?: Date;
+  @Field(() => [ResultUnion], { nullable: true, defaultValue: [] })
+  results?: Array<typeof ResultUnion>;
 
-  @Field(() => [ResultUnion])
-  results: Array<typeof ResultUnion>;
+  @Field(() => [String])
+  datasets: string[];
+
+  @Field(() => String, { nullable: true })
+  filter?: string;
+
+  @Field()
+  domain: string;
+
+  @Field(() => [String])
+  variables: string[];
+
+  @Field()
+  algorithm: Algorithm;
+
+  @Field()
+  name: string;
 }
+
+@ObjectType()
+export class PartialExperiment extends PartialType(Experiment) {}
diff --git a/api/src/engine/models/experiment/input/algorithm-parameter.input.ts b/api/src/engine/models/experiment/input/algorithm-parameter.input.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8eb4cb26b5dade932440b6fef169275988d33b03
--- /dev/null
+++ b/api/src/engine/models/experiment/input/algorithm-parameter.input.ts
@@ -0,0 +1,10 @@
+import { Field, InputType } from '@nestjs/graphql';
+
+@InputType()
+export class AlgorithmParamInput {
+  @Field()
+  name: string;
+
+  @Field(() => [String])
+  value: string[];
+}
diff --git a/api/src/engine/models/experiment/input/algorithm.input.ts b/api/src/engine/models/experiment/input/algorithm.input.ts
new file mode 100644
index 0000000000000000000000000000000000000000..54d26b7686559c39b311cee5e5496bce530b0cf5
--- /dev/null
+++ b/api/src/engine/models/experiment/input/algorithm.input.ts
@@ -0,0 +1,14 @@
+import { Field, InputType } from '@nestjs/graphql';
+import { AlgorithmParamInput } from './algorithm-parameter.input';
+
+@InputType()
+export class AlgorithmInput {
+  @Field()
+  name: string;
+
+  @Field(() => [AlgorithmParamInput], { nullable: true, defaultValue: [] })
+  parameters: AlgorithmParamInput[];
+
+  @Field()
+  type: string;
+}
diff --git a/api/src/engine/models/experiment/experiment-create.input.ts b/api/src/engine/models/experiment/input/experiment-create.input.ts
similarity index 80%
rename from api/src/engine/models/experiment/experiment-create.input.ts
rename to api/src/engine/models/experiment/input/experiment-create.input.ts
index d871eead0d40690fda47ec6b8ee5ff76bd173e6d..85a54049cffde188cd770237ba53ef1ccf847027 100644
--- a/api/src/engine/models/experiment/experiment-create.input.ts
+++ b/api/src/engine/models/experiment/input/experiment-create.input.ts
@@ -1,21 +1,22 @@
 import { Field, InputType } from '@nestjs/graphql';
+import { AlgorithmInput } from './algorithm.input';
 
 @InputType()
 export class ExperimentCreateInput {
   @Field(() => [String])
   datasets: string[];
 
-  @Field(() => [String])
-  variables: string[];
-
   @Field(() => String, { nullable: true })
   filter: string;
 
   @Field()
   domain: string;
 
+  @Field(() => [String])
+  variables: string[];
+
   @Field()
-  algorithm: string;
+  algorithm: AlgorithmInput;
 
   @Field()
   name: string;
diff --git a/api/src/engine/models/experiment/input/experiment-edit.input.ts b/api/src/engine/models/experiment/input/experiment-edit.input.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d37deb1e8d008d746fda7214bb6890142b74a12a
--- /dev/null
+++ b/api/src/engine/models/experiment/input/experiment-edit.input.ts
@@ -0,0 +1,10 @@
+import { Field, InputType } from '@nestjs/graphql';
+
+@InputType()
+export class ExperimentEditInput {
+  @Field({ nullable: true })
+  name?: string;
+
+  @Field({ nullable: true })
+  viewed?: boolean;
+}
diff --git a/api/src/engine/models/experiment/list-experiments.model.ts b/api/src/engine/models/experiment/list-experiments.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8f8592e52f1e3d85946d373a73b4edd00ac318f5
--- /dev/null
+++ b/api/src/engine/models/experiment/list-experiments.model.ts
@@ -0,0 +1,17 @@
+import { Field, ObjectType } from '@nestjs/graphql';
+import { Experiment } from './experiment.model';
+
+@ObjectType()
+export class ListExperiments {
+  @Field({ nullable: true, defaultValue: 0 })
+  currentPage?: number;
+
+  @Field({ nullable: true })
+  totalPages?: number;
+
+  @Field({ nullable: true })
+  totalExperiments?: number;
+
+  @Field(() => [Experiment])
+  experiments: Experiment[];
+}
diff --git a/api/src/engine/models/result/common/result-union.model.ts b/api/src/engine/models/result/common/result-union.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1f7b522c0a06a1c12f13cf2e608b49f2da233c77
--- /dev/null
+++ b/api/src/engine/models/result/common/result-union.model.ts
@@ -0,0 +1,24 @@
+import { createUnionType } from '@nestjs/graphql';
+import { GroupsResult } from '../groups-result.model';
+import { RawResult } from '../raw-result.model';
+import { TableResult } from '../table-result.model';
+
+export const ResultUnion = createUnionType({
+  name: 'ResultUnion',
+  types: () => [TableResult, RawResult, GroupsResult],
+  resolveType(value) {
+    if (value.headers) {
+      return TableResult;
+    }
+
+    if (value.listMax) {
+      return RawResult;
+    }
+
+    if (value.groups) {
+      return GroupsResult;
+    }
+
+    return null;
+  },
+});
diff --git a/api/src/engine/models/result/common/result.model.ts b/api/src/engine/models/result/common/result.model.ts
index ca86bfb4e109c44d0d4c06ea0e70ac05e3bf656a..e5e059738c16bb8297558add9aa51e7bce9791e2 100644
--- a/api/src/engine/models/result/common/result.model.ts
+++ b/api/src/engine/models/result/common/result.model.ts
@@ -1,7 +1,4 @@
-import { Field, ObjectType } from '@nestjs/graphql';
+import { ObjectType } from '@nestjs/graphql';
 
 @ObjectType()
-export abstract class Result {
-  @Field({ nullable: true })
-  groupBy?: string;
-}
+export abstract class Result {}
diff --git a/api/src/engine/models/result/dummy-result.model.ts b/api/src/engine/models/result/dummy-result.model.ts
deleted file mode 100644
index 99e36f5c90b9100e1cd46ed9fa67f613a46864b5..0000000000000000000000000000000000000000
--- a/api/src/engine/models/result/dummy-result.model.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { Field, ObjectType } from '@nestjs/graphql';
-import { Result } from './common/result.model';
-
-@ObjectType()
-export class DummyResult extends Result {
-  @Field()
-  name: string;
-
-  @Field(() => [[String]])
-  data: string[][];
-
-  @Field(() => [String])
-  listMax: string[];
-}
diff --git a/api/src/engine/models/result/groups-result.model.ts b/api/src/engine/models/result/groups-result.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e3de47038bb69b09615831c8c5dac1cf456d93df
--- /dev/null
+++ b/api/src/engine/models/result/groups-result.model.ts
@@ -0,0 +1,22 @@
+import { Field, ObjectType } from '@nestjs/graphql';
+import { ResultUnion } from './common/result-union.model';
+import { Result } from './common/result.model';
+
+@ObjectType()
+export class GroupResult {
+  public constructor(init?: Partial<GroupResult>) {
+    Object.assign(this, init);
+  }
+
+  @Field()
+  name: string;
+
+  @Field(() => [ResultUnion])
+  results: Array<typeof ResultUnion>;
+}
+
+@ObjectType()
+export class GroupsResult extends Result {
+  @Field(() => [GroupResult])
+  groups: GroupResult[];
+}
diff --git a/api/src/engine/models/result/raw-result.model.ts b/api/src/engine/models/result/raw-result.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5074e015cc483a3b4fe899f9608d8ddba76f0bfa
--- /dev/null
+++ b/api/src/engine/models/result/raw-result.model.ts
@@ -0,0 +1,12 @@
+import { Field, ObjectType } from '@nestjs/graphql';
+import { GraphQLJSONObject } from 'graphql-type-json';
+import { Result } from './common/result.model';
+
+@ObjectType()
+export class RawResult extends Result {
+  @Field(() => GraphQLJSONObject)
+  data: unknown;
+
+  @Field(() => [String], { defaultValue: [] })
+  listMax?: string[];
+}
diff --git a/api/src/schema.gql b/api/src/schema.gql
index c2ebe062948d88d817911b41942288f96c926b25..fc53b738b631a6dc35e5e162889f12f1c726df06 100644
--- a/api/src/schema.gql
+++ b/api/src/schema.gql
@@ -34,54 +34,125 @@ type Domain {
   rootGroup: Group!
 }
 
-type Header {
+type GroupResult {
   name: String!
-  type: String!
+  results: [ResultUnion!]!
 }
 
-type Experiment {
-  title: String!
-  uuid: String
-  created_at: DateTime
-  update_at: DateTime
-  finished_at: DateTime
-  results: [ResultUnion!]!
+union ResultUnion = TableResult | RawResult | GroupsResult
+
+type TableResult {
+  name: String!
+  data: [[String!]!]!
+  headers: [Header!]!
+}
+
+type RawResult {
+  data: JSONObject!
+  listMax: [String!]!
 }
 
 """
-A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format.
+The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
 """
-scalar DateTime
+scalar JSONObject @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf")
 
-union ResultUnion = TableResult | DummyResult
+type GroupsResult {
+  groups: [GroupResult!]!
+}
 
-type TableResult {
-  groupBy: String
+type Header {
   name: String!
-  data: [[String!]!]!
-  headers: [Header!]!
+  type: String!
 }
 
-type DummyResult {
-  groupBy: String
+type AlgorithmParameter {
   name: String!
-  data: [[String!]!]!
-  listMax: [String!]!
+  value: [String!]!
+}
+
+type Algorithm {
+  name: String!
+  parameters: [AlgorithmParameter!]
+  type: String!
+}
+
+type Experiment {
+  uuid: String
+  author: String
+  createdAt: Float
+  updateAt: Float
+  finishedAt: Float
+  viewed: Boolean
+  status: String
+  shared: Boolean!
+  results: [ResultUnion!]
+  datasets: [String!]!
+  filter: String
+  domain: String!
+  variables: [String!]!
+  algorithm: Algorithm!
+  name: String!
+}
+
+type PartialExperiment {
+  uuid: String
+  author: String
+  createdAt: Float
+  updateAt: Float
+  finishedAt: Float
+  viewed: Boolean
+  status: String
+  shared: Boolean
+  results: [ResultUnion!]
+  datasets: [String!]
+  filter: String
+  domain: String
+  variables: [String!]
+  algorithm: Algorithm
+  name: String
+}
+
+type ListExperiments {
+  currentPage: Float
+  totalPages: Float
+  totalExperiments: Float
+  experiments: [Experiment!]!
 }
 
 type Query {
   domains(ids: [String!] = []): [Domain!]!
+  experiments(name: String = "", page: Float = 0): ListExperiments!
+  expriment(uuid: String!): Experiment!
 }
 
 type Mutation {
-  createTransient(data: ExperimentCreateInput!): Experiment!
+  createExperiment(isTransient: Boolean = false, data: ExperimentCreateInput!): Experiment!
+  editExperiment(data: ExperimentEditInput!, uuid: String!): Experiment!
+  removeExperiment(uuid: String!): PartialExperiment!
 }
 
 input ExperimentCreateInput {
   datasets: [String!]!
-  variables: [String!]!
   filter: String
   domain: String!
-  algorithm: String!
+  variables: [String!]!
+  algorithm: AlgorithmInput!
+  name: String!
+}
+
+input AlgorithmInput {
   name: String!
+  parameters: [AlgorithmParamInput!] = []
+  type: String!
+}
+
+input AlgorithmParamInput {
+  name: String!
+  value: [String!]!
+}
+
+input ExperimentEditInput {
+  name: String
+  viewed: Boolean
 }