diff --git a/package.json b/package.json
index 06d658259063631455bef4d624ded367f1e8acce..f1b829d7a7f021dd7d4fbf76e6c5b7198de84b0f 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
     "async": "=2.4.1",
     "express": "^4.0.33",
     "js-yaml": "^3.8.2",
+    "json-2-csv": "^3.5.5",
     "monetdb": "^1.1.4",
     "osprey": "^0.3.2",
     "pg": "^6.1.5",
diff --git a/specs/blendb-api-v1.raml b/specs/blendb-api-v1.raml
index e5c69cb53a278be1c4194339e913e13da5e89690..4de37301acda02380488b2d3cbe51e9862e143b1 100644
--- a/specs/blendb-api-v1.raml
+++ b/specs/blendb-api-v1.raml
@@ -271,6 +271,18 @@ traits:
                 description: |
                     Fields to be returned.
                 type: string
+    - formatable:
+        queryParameters:
+            format:
+                description: |
+                    Response format. Defines if the response objects will be a
+                    json or a csv-like file. The default value is json.
+                    The csv-like formats are: csv, ssv and tsv which the
+                    separator is comma, semi-colon and tab respectively.
+                example: "ssv+"
+                required: false
+                pattern: "^json$|^csv$|^ssv$|^tsv$"
+                type: string
 
 /metrics:
     description: |
@@ -279,6 +291,7 @@ traits:
         system and their descriptions.
     securedBy: [ null, oauth_2_0 ]
     get:
+        is: [ formatable ]
 /sources:
     description: |
         A Source represents a type of object that can be inserted in the database.
@@ -286,6 +299,7 @@ traits:
         system and their descriptions
     securedBy: [ null, oauth_2_0 ]    
     get:
+        is: [ formatable ]
 
 /dimensions:
     description: |
@@ -294,12 +308,14 @@ traits:
         the system and their descriptions.
     securedBy: [ null, oauth_2_0 ]
     get:
+        is: [ formatable ]
 /enumtypes:
     description: |
         A EnumType is short for enumerable type. This is a special data type that only accepts a few possible values. This
         collection allows the user to list all the enumerable types available in the system, their descriptions and possible
         values.
     get:    
+        is: [ formatable ]
     securedBy: [ null, oauth_2_0 ]    
 /data:
     description: |
@@ -309,7 +325,7 @@ traits:
       start/end dates to refine your query.
     type: base
     get:
-        is: [ filtered ]
+        is: [ filtered, formatable ]
         queryParameters:
             metrics:
                 description: |
diff --git a/src/api/controllers/data.spec.ts b/src/api/controllers/data.spec.ts
index 83710e99d13d7bc3041bea4bcf85d19c6b9fea18..2e1f58cb5a770807a8a373bb7414087733b2dd5e 100644
--- a/src/api/controllers/data.spec.ts
+++ b/src/api/controllers/data.spec.ts
@@ -23,12 +23,15 @@ import { expect } from "chai";
 import * as server from "../../main";
 import { dataCtrlScenario as tests } from "../../../test/scenario";
 import { Query } from "../../common/query";
+import { waterfall } from "async";
+import * as fs from "fs";
 
 interface StrQuery {
     metrics: string;
     dimensions: string;
     filters?: string;
     sort?: string;
+    format?: string;
 }
 
 function parseQuery(obj: Query): StrQuery {
@@ -307,4 +310,72 @@ describe("API data controller", () => {
             .end(done);
     });
 
+    it("should respond 200 and get some data with format as csv", (done) => {
+        waterfall([(cb: (err: Error, data: string) => void) => {
+            fs.readFile("test/files/data.csv", "utf8", (err, data) => {
+                cb(err, data);
+            });
+        }
+        , (file: string, cb: (err: Error) => void) => {
+            let query = parseQuery(tests.csv);
+            query.format = "csv";
+            request(server)
+                .get("/v1/data")
+                .query(query)
+                .expect(200)
+                .expect((res: any) => {
+                    expect(res.text).to.be.eql(file);
+                })
+                .end(cb);
+        }], (err) => {
+            expect(err).to.be.eql(null);
+            done();
+        });
+    });
+
+    it("should respond 200 and get some data with format as ssv", (done) => {
+        waterfall([(cb: (err: Error, data: string) => void) => {
+            fs.readFile("test/files/data.ssv", "utf8", (err, data) => {
+                cb(err, data);
+            });
+        }
+        , (file: string, cb: (err: Error) => void) => {
+            let query = parseQuery(tests.csv);
+            query.format = "ssv";
+            request(server)
+                .get("/v1/data")
+                .query(query)
+                .expect(200)
+                .expect((res: any) => {
+                    expect(res.text).to.be.eql(file);
+                })
+                .end(cb);
+        }], (err) => {
+            expect(err).to.be.eql(null);
+            done();
+        });
+    });
+
+    it("should respond 200 and get some data with format as tsv", (done) => {
+        waterfall([(cb: (err: Error, data: string) => void) => {
+            fs.readFile("test/files/data.tsv", "utf8", (err, data) => {
+                cb(err, data);
+            });
+        }
+        , (file: string, cb: (err: Error) => void) => {
+            let query = parseQuery(tests.csv);
+            query.format = "tsv";
+            request(server)
+                .get("/v1/data")
+                .query(query)
+                .expect(200)
+                .expect((res: any) => {
+                    expect(res.text).to.be.eql(file);
+                })
+                .end(cb);
+        }], (err) => {
+            expect(err).to.be.eql(null);
+            done();
+        });
+    });
 });
diff --git a/src/api/controllers/data.ts b/src/api/controllers/data.ts
index a6e4b1f343f4baf3252f347cc5c717ccea9391dd..3cd155c3cb14cb044a8f3c43dfffaf9658c7c321 100644
--- a/src/api/controllers/data.ts
+++ b/src/api/controllers/data.ts
@@ -45,6 +45,12 @@ export class DataCtrl {
         if (req.query.sort) {
             sort = req.query.sort.split(",").filter((item: string) => item !== "");
         }
+
+        let format = "json";
+        if (req.query.format) {
+            format = req.query.format;
+        }
+
         let view;
 
         try {
@@ -102,7 +108,26 @@ export class DataCtrl {
                 return;
             }
 
-            res.status(200).json(result);
+            if (format === "json") {
+                res.status(200).json(result);
+            }
+
+            else {
+                req.csvParser(result, format, (error: Error, csv: string) => {
+                    if (error) {
+                        res.status(500).json({
+                            message: "Error generating csv file. " +
+                            "Try json format.",
+                            error: error
+                        });
+                        return;
+                    }
+
+                    res.setHeader("Content-Type", "text/csv");
+                    res.setHeader("Content-disposition", "attachment;filename=data.csv");
+                    res.status(200).send(csv);
+                });
+            }
             return;
         });
     }
diff --git a/src/api/controllers/engine.spec.ts b/src/api/controllers/engine.spec.ts
index 28f71adfc05b58429e9802e8b74a6dc0ab0beb5b..7290c349888a8623892738e7f32748dd73854344 100644
--- a/src/api/controllers/engine.spec.ts
+++ b/src/api/controllers/engine.spec.ts
@@ -19,8 +19,10 @@
  */
 
 import * as request from "supertest";
+import * as fs from "fs";
 import { expect } from "chai";
 import * as server from "../../main";
+import { waterfall } from "async";
 
 describe("API engine controller", () => {
 
@@ -68,4 +70,25 @@ describe("API engine controller", () => {
             .end(done);
     });
 
+    it("should respond 200 and the list of metrics (in csv)", (done) => {
+        waterfall([(cb: (err: Error, data: string) => void) => {
+            fs.readFile("test/files/metrics.csv", "utf8", (err, data) => {
+                cb(err, data);
+            });
+        }
+        , (file: string, cb: (err: Error) => void) => {
+            request(server)
+                .get("/v1/metrics")
+                .query({format: "ssv"})
+                .expect(200)
+                .expect((res: any) => {
+                    expect(res.text).to.be.eql(file);
+                })
+                .end(cb);
+        }], (err) => {
+            expect(err).to.be.eql(null);
+            done();
+        });
+    });
+
 });
diff --git a/src/api/controllers/engine.ts b/src/api/controllers/engine.ts
index 4fde6269537dca47013104a91200a53527965e91..802acc1ae49f898cc3fc32568d968ab09ac88003 100644
--- a/src/api/controllers/engine.ts
+++ b/src/api/controllers/engine.ts
@@ -27,6 +27,42 @@ import { Request } from "../types";
  * engine object that API users can use to create queries.
  */
 export class EngineCtrl {
+    /**
+     * Auxiliary function that returns engine information.
+     * @param list - List of objects to return
+     * @param req - Object with request information
+     * @param res - Object used to create and send the response
+     * @param next - Call next middleware or controller. Not used but required
+     * by typescript definition of route.
+     */
+    private static respondList(list: any[], fileName: string, req: Request, res: express.Response, next: express.NextFunction) {
+        let format = "json";
+        if (req.query.format) {
+            format = req.query.format;
+        }
+
+        if (format === "json") {
+            res.status(200).json(list);
+        }
+
+        else {
+            req.csvParser(list, format, (error: Error, csv: string) => {
+                if (error) {
+                    res.status(500).json({
+                        message: "Error generating csv file. " +
+                        "Try json format.",
+                        error: error
+                    });
+                    return;
+                }
+
+                const disposition = "attachment;filename=" + fileName + ".csv";
+                res.setHeader("Content-Type", "text/csv");
+                res.setHeader("Content-disposition", disposition);
+                res.status(200).send(csv);
+            });
+        }
+    }
     /**
      * Route that returns the list of available metrics.
      * @param req - Object with request information
@@ -35,7 +71,8 @@ export class EngineCtrl {
      * by typescript definition of route.
      */
     public static metrics(req: Request, res: express.Response, next: express.NextFunction) {
-        res.status(200).json(req.engine.getMetricsDescription());
+        const metrics = req.engine.getMetricsDescription();
+        EngineCtrl.respondList(metrics, "metrics", req, res, next);
     }
 
     /**
@@ -46,7 +83,8 @@ export class EngineCtrl {
      * by typescript definition of route.
      */
     public static dimensions(req: Request, res: express.Response, next: express.NextFunction) {
-        res.status(200).json(req.engine.getDimensionsDescription());
+        const dimensions = req.engine.getDimensionsDescription();
+        EngineCtrl.respondList(dimensions, "dimensions", req, res, next);
     }
 
     /**
@@ -57,7 +95,8 @@ export class EngineCtrl {
      * by typescript definition of route.
      */
     public static enumTypes(req: Request, res: express.Response, next: express.NextFunction) {
-        res.status(200).json(req.engine.getEnumTypesDescription());
+        const enumTypes = req.engine.getEnumTypesDescription();
+        EngineCtrl.respondList(enumTypes, "enums", req, res, next);
     }
 
     /**
@@ -68,6 +107,7 @@ export class EngineCtrl {
      * by typescript definition of route.
      */
     public static sources(req: Request, res: express.Response, next: express.NextFunction) {
-       res.status(200).json(req.engine.getSourcesDescription());
+       const sources = req.engine.getSourcesDescription();
+       EngineCtrl.respondList(sources, "sources", req, res, next);
     }
 }
diff --git a/src/api/middlewares/csv.ts b/src/api/middlewares/csv.ts
new file mode 100644
index 0000000000000000000000000000000000000000..42540aae3cfc6d3765a40e0d6e48f1c7f289c343
--- /dev/null
+++ b/src/api/middlewares/csv.ts
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015-2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blendb.
+ *
+ * blendb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * blendb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with blendb.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import * as json2csv from "json-2-csv";
+import { Middleware } from "../types";
+
+/**
+ * Creates a csv parser and middleaew that
+ * inserts the parser into the request objects.
+ */
+export function CsvMw(): Middleware {
+    return function csvMiddleware(req, res, next) {
+        req.csvParser = function parseCsv(json: any, format: string, cb) {
+            const separator = format.substring(0, 1);
+
+            let sep = ",";
+            if (separator === "s") {
+                sep = ";";
+            }
+
+            else if (separator === "t"){
+                sep = "\t";
+            }
+
+            json2csv.json2csv(json, cb, {
+                delimiter: {
+                    field: sep
+                    , wrap: "\""
+                    , eol: "\n"
+                }
+                , prependHeader: true
+            });
+        };
+        next();
+    };
+
+}
diff --git a/src/api/types.ts b/src/api/types.ts
index 0fe099f9690f47667205d7bb723da6168f9b984b..469b6adc6b48b53ca773fd0c9bf42556e96a99c4 100644
--- a/src/api/types.ts
+++ b/src/api/types.ts
@@ -35,6 +35,8 @@ export interface Request extends express.Request {
     engine: Engine;
     /** A adapter object. Used to communicate with the database in use. */
     adapter: Adapter;
+    /** A csvParser function. Used to parse json object into csv file. */
+    csvParser: (json: any, format: string, cb: (err: Error, csv?: string));
 }
 
 /**
diff --git a/src/main.ts b/src/main.ts
index 0710b3cc5db45c3b2d378e021a10c0bc00c798f4..4eb837ddb67c69e9fe7439a721ce670cbd5ddce9 100755
--- a/src/main.ts
+++ b/src/main.ts
@@ -40,7 +40,7 @@ import { ConfigParser } from "./util/configParser";
 let configPath;
 
 /** @hidden */
-if(process.env.BLENDB_SCHEMA_FILE){
+if (process.env.BLENDB_SCHEMA_FILE) {
     configPath = process.env.BLENDB_SCHEMA_FILE;
 }
 else{
@@ -54,8 +54,10 @@ const config = ConfigParser.parse(configPath);
 import { EngineMw } from "./api/middlewares/engine";
 import { PostgresMw, MonetMw } from "./api/middlewares/adapter";
 import { ErrorMw } from "./api/middlewares/error";
+import { CsvMw } from "./api/middlewares/csv";
 
 app.use(EngineMw(config));
+app.use(CsvMw());
 if (config.adapters[0] === "postgres") {
     app.use(PostgresMw(config.connections[0]));
 }
diff --git a/src/util/scenarioHandler.ts b/src/util/scenarioHandler.ts
index ae981185caef05afaf3a9488cd0f5dea29b9a7da..bb2de85715ff1e36320035cfd58071ec05f3b9d7 100644
--- a/src/util/scenarioHandler.ts
+++ b/src/util/scenarioHandler.ts
@@ -173,4 +173,8 @@ export interface DataCtrlScenario {
      * The products that are the most expensive
      */
     expensive: Query;
+    /**
+     * The sellers average age by cpf and sex
+     */
+    csv: Query;
 }
diff --git a/test/files/data.csv b/test/files/data.csv
new file mode 100644
index 0000000000000000000000000000000000000000..47783fd0ee7db1c1425741032efe42f9605048e0
--- /dev/null
+++ b/test/files/data.csv
@@ -0,0 +1,6 @@
+dim:seller:sex,dim:seller:cpf,met:seller:avg:age
+male,604.424.718-07,27
+female,575.657.111-60,26
+nonbinary,977.221.375-39,24
+undecided,344.805.128-45,23
+female,885.517.020-17,25
\ No newline at end of file
diff --git a/test/files/data.ssv b/test/files/data.ssv
new file mode 100644
index 0000000000000000000000000000000000000000..fa76b7ef2d198c5031c824bfd2c3d91aad9d68e9
--- /dev/null
+++ b/test/files/data.ssv
@@ -0,0 +1,6 @@
+dim:seller:sex;dim:seller:cpf;met:seller:avg:age
+male;604.424.718-07;27
+female;575.657.111-60;26
+nonbinary;977.221.375-39;24
+undecided;344.805.128-45;23
+female;885.517.020-17;25
\ No newline at end of file
diff --git a/test/files/data.tsv b/test/files/data.tsv
new file mode 100644
index 0000000000000000000000000000000000000000..70d90f86559c0d52b753065211101ec9f914b8f3
--- /dev/null
+++ b/test/files/data.tsv
@@ -0,0 +1,6 @@
+dim:seller:sex	dim:seller:cpf	met:seller:avg:age
+male	604.424.718-07	27
+female	575.657.111-60	26
+nonbinary	977.221.375-39	24
+undecided	344.805.128-45	23
+female	885.517.020-17	25
\ No newline at end of file
diff --git a/test/files/metrics.csv b/test/files/metrics.csv
new file mode 100644
index 0000000000000000000000000000000000000000..468d068440ee978ed90cc992e803228f9a833497
--- /dev/null
+++ b/test/files/metrics.csv
@@ -0,0 +1,17 @@
+name;aggregation;dataType;description
+met:seller:avg:age;avg;float;The seller average age
+met:seller:max:age;max;integer;The seller highest age
+met:seller:min:age;min;integer;The seller lowest age
+met:seller:count:age;count;integer;The number of seller's
+met:product:avg:pricein;avg;float;The average product pricein
+met:product:max:pricein;max;float;The highest product pricein
+met:product:min:pricein;min;float;The lowest product pricein
+met:product:avg:priceout;avg;float;The average product priceout
+met:product:max:priceout;max;float;The highest product priceout
+met:product:min:priceout;min;float;The lowest product priceout
+met:sell:sum:quantity;sum;integer;The sum of sales quantity
+met:sell:avg:quantity;avg;float;The average of sales quantity
+met:sell:count:quantity;count;integer;The total number of sales
+met:buyout:avg:quantity;avg;float;The average of quantity bought
+met:buyout:max:quantity;max;integer;The highest quantity bought
+met:buyout:min:quantity;min;integer;The lowest quantity bought
\ No newline at end of file
diff --git a/test/scenario.ts b/test/scenario.ts
index ad807b8260b1ebd863689835d6785b63ead2eb92..d598f79ecd548b1ea24b87d8cf42048bede546b8 100644
--- a/test/scenario.ts
+++ b/test/scenario.ts
@@ -334,6 +334,10 @@ let qOpts : {[key: string]: QueryOpts} = {
         metrics: [mets["met:seller:count:age"]],
         dimensions: []
     },
+    "csv": {
+        metrics: [mets["met:seller:avg:age"]],
+        dimensions: [dims["dim:seller:cpf"], dims["dim:seller:sex"]]
+    }
 }
 
 const queries : {[key: string]: Query} = {};
@@ -437,4 +441,5 @@ export const dataCtrlScenario: DataCtrlScenario = {
     correct: queries["correct"],
     clausal: queries["clausal"],
     expensive: queries["expensive"],
+    csv: queries["csv"],
 };
diff --git a/yarn.lock b/yarn.lock
index 96d8f20df54ea37887898695adfa575f4fa30f9a..5bfc5e3d1b634079e6de4c157136677df15d7d83 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -725,6 +725,13 @@ decamelize@^1.0.0, decamelize@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
 
+deeks@2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/deeks/-/deeks-2.2.1.tgz#4de360652998fd0a681153a9ffde5dcc6c983f4a"
+  integrity sha512-D2Qu3Fv5zBtBzXjXIUgWPRYn30d/IG6SCPOKIz42+LVTwhPeRI5+DAxdzap0vI2zYheiErIpVLwaUQBoA/iENw==
+  dependencies:
+    underscore "1.9.1"
+
 deep-eql@^0.1.3:
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
@@ -810,6 +817,11 @@ digest-header@^0.0.1:
   dependencies:
     utility "0.1.11"
 
+doc-path@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/doc-path/-/doc-path-2.0.1.tgz#d2adb8bcd31c895b17b92f61eff39aaec04430d2"
+  integrity sha512-/CCG157H//3l513omROUzaREChY/OYpxqYXvQcv7gsrwGfjVOh5d/1gJigHJ6iTnO77pA8rMLZ63CgEPEM6+9Q==
+
 dom-serializer@0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
@@ -1593,6 +1605,15 @@ jsesc@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
 
+json-2-csv@^3.5.5:
+  version "3.5.5"
+  resolved "https://registry.yarnpkg.com/json-2-csv/-/json-2-csv-3.5.5.tgz#555d493547086a34da6e36672f5ea1849ebb6789"
+  integrity sha512-7BlKbejl42pmzoamfH+OFsNkVtPtWUuBJCCh/rhjf32fPTol5UwQGp051cf+qFfDHu0iQssBEzwRIDoTcD3MAw==
+  dependencies:
+    deeks "2.2.1"
+    doc-path "2.0.1"
+    underscore "1.9.1"
+
 json-schema-compatibility@1.1.0, json-schema-compatibility@^1.0.1:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/json-schema-compatibility/-/json-schema-compatibility-1.1.0.tgz#1a8981778cda0c38187298d999d089e51af282df"
@@ -3078,6 +3099,11 @@ underscore@1.8.3:
   version "1.8.3"
   resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
 
+underscore@1.9.1:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961"
+  integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==
+
 universalify@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"