diff --git a/api/src/common/interfaces/utilities.interface.ts b/api/src/common/interfaces/utilities.interface.ts
index db02ef99e3f4c67f65f320f1d0bfe1a2a6b832f5..0a0978c5ab64ef2474bea31709697c3d002a5456 100644
--- a/api/src/common/interfaces/utilities.interface.ts
+++ b/api/src/common/interfaces/utilities.interface.ts
@@ -3,6 +3,7 @@ import { ResultUnion } from 'src/engine/models/result/common/result-union.model'
 export type Dictionary<T> = { [key: string]: T };
 
 export type ExperimentResult = typeof ResultUnion;
+export type AlgoResults = ExperimentResult[];
 
 export enum MIME_TYPES {
   ERROR = 'text/plain+error',
diff --git a/api/src/engine/connectors/exareme/handlers/algorithms/area.handler.ts b/api/src/engine/connectors/exareme/handlers/algorithms/area.handler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..198175a884dce0f40293a5cfec038f3de2920973
--- /dev/null
+++ b/api/src/engine/connectors/exareme/handlers/algorithms/area.handler.ts
@@ -0,0 +1,49 @@
+import * as jsonata from 'jsonata'; // old import style needed due to 'export = jsonata'
+import { AlgoResults } from 'src/common/interfaces/utilities.interface';
+import { ResultChartExperiment } from '../../interfaces/experiment/result-chart-experiment.interface';
+import BaseHandler from '../base.handler';
+
+export default class AreaHandler extends BaseHandler {
+  static readonly transform = jsonata(`
+  ({
+      "name": data.title.text,
+      "xAxis": {
+          "label": data.xAxis.title.text
+      },
+      "yAxis": {
+          "label": data.yAxis.title.text
+      },
+      "lines": [
+          {
+              "label": "ROC curve",
+              "x": data.series.data.$[0],
+              "y": data.series.data.$[1],
+              "type": 0
+          }
+      ]
+  })
+  `);
+
+  canHandle(input: ResultChartExperiment): boolean {
+    return (
+      input.type === 'application/vnd.highcharts+json' &&
+      input.data.chart.type === 'area'
+    );
+  }
+
+  handle(algorithm: string, data: unknown, res: AlgoResults): void {
+    let req = data;
+    const inputs = data as ResultChartExperiment[];
+
+    if (inputs) {
+      inputs
+        .filter(this.canHandle)
+        .map((input) => AreaHandler.transform.evaluate(input))
+        .forEach((input) => res.push(input));
+
+      req = JSON.stringify(inputs.filter((input) => !this.canHandle(input)));
+    }
+
+    this.next?.handle(algorithm, req, res);
+  }
+}
diff --git a/api/src/engine/connectors/exareme/handlers/algorithms/descriptive.handler.ts b/api/src/engine/connectors/exareme/handlers/algorithms/descriptive.handler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a314a6bf6840e6b447a2ee5ddd881244b5a10793
--- /dev/null
+++ b/api/src/engine/connectors/exareme/handlers/algorithms/descriptive.handler.ts
@@ -0,0 +1,131 @@
+import { AlgoResults } from 'src/common/interfaces/utilities.interface';
+import {
+  GroupResult,
+  GroupsResult,
+} from 'src/engine/models/result/groups-result.model';
+import { ResultExperiment } from '../../interfaces/experiment/result-experiment.interface';
+import BaseHandler from '../base.handler';
+import * as jsonata from 'jsonata'; // old import style needed due to 'export = jsonata'
+
+export default class DescriptiveHandler extends BaseHandler {
+  private static readonly headerDescriptive = `
+$fnum := function($x) { $type($x) = 'number' ? $round($number($x),3) : $x };
+
+$e := function($x, $r) {($x != null) ? $fnum($x) : ($r ? $r : '')};
+
+$fn := function($o, $prefix) {
+    $type($o) = 'object' ? 
+    $each($o, function($v, $k) {(
+        $type($v) = 'object' ? { $k: $v.count & ' (' & $v.percentage & '%)' } : {
+            $k: $v
+        }
+    )}) ~> $merge()
+    : {}
+};`;
+
+  static readonly descriptiveModelToTables = jsonata(`
+(   
+    ${this.headerDescriptive}
+    
+    $vars := $count($keys(data.model.*.data))-1;
+    $varNames := $keys(data.model.*.data);
+    $model := data.model;
+
+    [[0..$vars].(
+        $i := $;
+        $varName := $varNames[$i];
+        $ks := $keys($model.*.data.*[$i][$type($) = 'object']);
+        {
+            'name': $varName,
+            'headers': $append("", $keys($$.data.model)).{
+                'name': $,
+                'type': 'string'
+            },
+            'data': [
+                [$varName, $model.*.($e(num_total))],
+                ['Datapoints', $model.*.($e(num_datapoints))],
+                ['Nulls', $model.*.($e(num_nulls))],
+                ($lookup($model.*.data, $varName).($fn($)) ~> $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)})[]
+            ]
+        }
+    )]  
+)`);
+
+  static readonly descriptiveSingleToTables = jsonata(`
+( 
+    ${this.headerDescriptive}
+
+    data.[
+        $.single.*@$p#$i.(
+            $ks := $keys($p.*.data[$type($) = 'object']);
+            {
+            'name': $keys(%)[$i],
+            'headers': $append("", $keys(*)).{
+                'name': $,
+                'type': 'string'
+            },
+            'data' : [
+                [$keys(%)[$i], $p.*.($e(num_total))],
+                ['Datapoints', $p.*.($e(num_datapoints))],
+                ['Nulls', $p.*.($e(num_nulls))],
+                ($p.*.data.($fn($)) ~> $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)})[]
+            ]
+        })
+    ]
+)
+`);
+
+  descriptiveDataToTableResult(data: ResultExperiment): GroupsResult {
+    const result = new GroupsResult();
+
+    result.groups = [
+      new GroupResult({
+        name: 'Variables',
+        description: 'Descriptive statistics for the variables of interest.',
+        results: DescriptiveHandler.descriptiveSingleToTables.evaluate(data),
+      }),
+    ];
+
+    result.groups.push(
+      new GroupResult({
+        name: 'Model',
+        description:
+          'Intersection table for the variables of interest as it appears in the experiment.',
+        results: DescriptiveHandler.descriptiveModelToTables.evaluate(data),
+      }),
+    );
+
+    return result;
+  }
+
+  handle(algorithm: string, data: unknown, res: AlgoResults): void {
+    let req = data;
+
+    if (algorithm.toLowerCase() === 'descriptive_stats') {
+      const inputs = data as ResultExperiment[];
+
+      inputs
+        .filter((input) => input.type === 'application/json')
+        .map((input) => this.descriptiveDataToTableResult(input))
+        .forEach((input) => res.push(input));
+
+      req = JSON.stringify(
+        inputs.filter((input) => input.type !== 'application/json'),
+      );
+    }
+
+    this.next?.handle(algorithm, req, res);
+  }
+}
diff --git a/api/src/engine/connectors/exareme/handlers/algorithms/heat-map.handler.ts b/api/src/engine/connectors/exareme/handlers/algorithms/heat-map.handler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..20591ad7589b9e075d2266a22ae5ccd7f0acd7a8
--- /dev/null
+++ b/api/src/engine/connectors/exareme/handlers/algorithms/heat-map.handler.ts
@@ -0,0 +1,46 @@
+import { AlgoResults } from 'src/common/interfaces/utilities.interface';
+import { ResultChartExperiment } from '../../interfaces/experiment/result-chart-experiment.interface';
+import BaseHandler from '../base.handler';
+import * as jsonata from 'jsonata'; // old import style needed due to 'export = jsonata'
+
+export default class HeatMapHandler extends BaseHandler {
+  static readonly transform = jsonata(`
+  (
+      {
+          "name": data.title.text,
+          "xAxis": {
+              "categories": data.xAxis.categories,
+              "label": data.xAxis.label
+          },
+          "yAxis": {
+              "categories": data.yAxis.categories,
+              "label": data.yAxis.label
+          },
+          "matrix": $toMat(data.series.data)
+      }
+  )
+  `);
+
+  canHandle(input: ResultChartExperiment): boolean {
+    return (
+      input.type.toLowerCase() === 'application/vnd.highcharts+json' &&
+      input.data.chart.type.toLowerCase() === 'heatmap'
+    );
+  }
+
+  handle(algorithm: string, data: unknown, res: AlgoResults): void {
+    let req = data;
+    const inputs = data as ResultChartExperiment[];
+
+    if (inputs) {
+      inputs
+        .filter(this.canHandle)
+        .map((input) => HeatMapHandler.transform.evaluate(input))
+        .forEach((input) => res.push(input));
+
+      req = JSON.stringify(inputs.filter((input) => !this.canHandle(input)));
+    }
+
+    this.next?.handle(algorithm, req, res);
+  }
+}
diff --git a/api/src/engine/connectors/exareme/handlers/algorithms/pearson.handler.ts b/api/src/engine/connectors/exareme/handlers/algorithms/pearson.handler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..16702657df654d7c282efe54094ce46e4fb5e497
--- /dev/null
+++ b/api/src/engine/connectors/exareme/handlers/algorithms/pearson.handler.ts
@@ -0,0 +1,47 @@
+import { Expression } from 'jsonata';
+import * as jsonata from 'jsonata'; // old import style needed due to 'export = jsonata'
+import { AlgoResults } from 'src/common/interfaces/utilities.interface';
+import { HeatMapResult } from 'src/engine/models/result/heat-map-result.model';
+import BaseHandler from '../base.handler';
+
+export default class PearsonHandler extends BaseHandler {
+  readonly transform: Expression = jsonata(`
+  (
+    $params := ['correlations', 'p-values', 'low_confidence_intervals', 'high_confidence_intervals'];
+
+    $.$sift(function($v, $k) {$k in $params}).$each(function($v, $k) {
+        {
+            'name': $k,
+            'xAxis': {
+                'categories': $v.variables
+            },
+            'yAxis': {
+                'categories': $keys($v.$sift(function($val, $key) {$key ~> /^(?!variables$)/}))
+            },
+            'matrix': $v.$sift(function($val, $key) {$key ~> /^(?!variables$)/}).$each(function($val, $key) {$val})[]
+            }
+    })
+  )`);
+
+  canHandle(algorithm: string): boolean {
+    return algorithm.toLocaleLowerCase() === 'pearson';
+  }
+
+  handle(algorithm: string, data: unknown, res: AlgoResults): void {
+    if (this.canHandle(algorithm)) {
+      try {
+        const results = this.transform.evaluate(data) as HeatMapResult[];
+        results
+          .filter((heatMap) => heatMap.matrix.length > 0 && heatMap.name)
+          .forEach((heatMap) => res.push(heatMap));
+      } catch (e) {
+        PearsonHandler.logger.warn(
+          'An error occur when converting result from Pearson',
+        );
+        PearsonHandler.logger.verbose(JSON.stringify(data));
+      }
+    }
+
+    this.next?.handle(algorithm, data, res);
+  }
+}
diff --git a/api/src/engine/connectors/exareme/handlers/algorithms/raw.handler.ts b/api/src/engine/connectors/exareme/handlers/algorithms/raw.handler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..810be82cecd06bb193adaefb88fc50ccbdaa2fad
--- /dev/null
+++ b/api/src/engine/connectors/exareme/handlers/algorithms/raw.handler.ts
@@ -0,0 +1,29 @@
+import {
+  AlgoResults,
+  MIME_TYPES,
+} from 'src/common/interfaces/utilities.interface';
+import { RawResult } from 'src/engine/models/result/raw-result.model';
+import { ResultExperiment } from '../../interfaces/experiment/result-experiment.interface';
+import BaseHandler from '../base.handler';
+
+export default class RawHandler extends BaseHandler {
+  dataToRaw = (algo: string, result: ResultExperiment): RawResult => {
+    let data = result;
+
+    if (algo === 'CART') {
+      data = { ...data, type: MIME_TYPES.JSONBTREE };
+    }
+
+    return { rawdata: data };
+  };
+
+  handle(algorithm: string, data: unknown, res: AlgoResults): void {
+    const inputs = data as ResultExperiment[];
+
+    inputs
+      .map((input) => this.dataToRaw(algorithm, input))
+      .forEach((input) => res.push(input));
+
+    this.next?.handle(algorithm, data, res);
+  }
+}
diff --git a/api/src/engine/connectors/exareme/handlers/base.handler.ts b/api/src/engine/connectors/exareme/handlers/base.handler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2f72f190258e37f1bd689cdd6163b32699586b52
--- /dev/null
+++ b/api/src/engine/connectors/exareme/handlers/base.handler.ts
@@ -0,0 +1,18 @@
+import { Logger } from '@nestjs/common';
+import { AlgoResults } from 'src/common/interfaces/utilities.interface';
+import ResultHandler from './result-handler.interface';
+
+export default abstract class BaseHandler implements ResultHandler {
+  protected static readonly logger = new Logger(this.name);
+
+  next: ResultHandler = null;
+
+  setNext(h: ResultHandler): ResultHandler {
+    this.next = h;
+    return h;
+  }
+
+  handle(algorithm: string, data: unknown, res: AlgoResults): void {
+    this.next?.handle(algorithm, data, res);
+  }
+}
diff --git a/api/src/engine/connectors/exareme/handlers/index.ts b/api/src/engine/connectors/exareme/handlers/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7e153ece232bc26a5a2de18d65265bdc1b34f0eb
--- /dev/null
+++ b/api/src/engine/connectors/exareme/handlers/index.ts
@@ -0,0 +1,19 @@
+import { AlgoResults } from 'src/common/interfaces/utilities.interface';
+import AreaHandler from './algorithms/area.handler';
+import DescriptiveHandler from './algorithms/descriptive.handler';
+import HeatMapHandler from './algorithms/heat-map.handler';
+import {
+  default as PearsonHandler,
+  default as RawHandler,
+} from './algorithms/raw.handler';
+
+const last = new RawHandler(); // should be last handler as it works as a fallback (if other handlers could not process the results)
+const start = new PearsonHandler()
+  .setNext(new AreaHandler())
+  .setNext(new DescriptiveHandler())
+  .setNext(new HeatMapHandler())
+  .setNext(last);
+
+export default (algo: string, data: unknown, res: AlgoResults) => {
+  start.handle(algo, data, res);
+};
diff --git a/api/src/engine/connectors/exareme/handlers/result-handler.interface.ts b/api/src/engine/connectors/exareme/handlers/result-handler.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..93f98a9e3043a793a08b233ae66965ebc1e93495
--- /dev/null
+++ b/api/src/engine/connectors/exareme/handlers/result-handler.interface.ts
@@ -0,0 +1,7 @@
+import { AlgoResults } from 'src/common/interfaces/utilities.interface';
+
+// produce algo handler
+export default interface ResultHandler {
+  setNext(h: ResultHandler): ResultHandler;
+  handle(algorithm: string, data: unknown, res: AlgoResults): void;
+}
diff --git a/api/src/engine/models/result/common/chart-axis.model.ts b/api/src/engine/models/result/common/chart-axis.model.ts
index 16fc1f68a10e379b0bf4e45225c7912710d1d34d..1b9bc68960fdbbb89241794afb4f827957d23c96 100644
--- a/api/src/engine/models/result/common/chart-axis.model.ts
+++ b/api/src/engine/models/result/common/chart-axis.model.ts
@@ -2,9 +2,13 @@ import { ObjectType, Field } from '@nestjs/graphql';
 
 @ObjectType()
 export class ChartAxis {
-  @Field({ nullable: true, defaultValue: '' })
+  @Field({ nullable: true, defaultValue: '', description: 'label of the Axis' })
   label?: string;
 
-  @Field(() => [String], { nullable: true, defaultValue: [] })
+  @Field(() => [String], {
+    nullable: true,
+    defaultValue: [],
+    description: 'label of each element on this Axis',
+  })
   categories?: string[];
 }
diff --git a/api/src/schema.gql b/api/src/schema.gql
index 4d248dc43d05871c60002fd581ba9a9a41f0ff07..b940e0ec06d23a0e87f41a791a669163fb88fe47 100644
--- a/api/src/schema.gql
+++ b/api/src/schema.gql
@@ -133,7 +133,10 @@ type LineChartResult {
 }
 
 type ChartAxis {
+  """label of the Axis"""
   label: String
+
+  """label of each element on this Axis"""
   categories: [String!]
 }